Bagaimana Anda secara terprogram memperbarui parameter kueri di react-router?

117

Saya tidak bisa menemukan cara memperbarui parameter kueri dengan react-router tanpa menggunakan <Link/>. hashHistory.push(url)tampaknya tidak mendaftarkan parameter kueri, dan sepertinya Anda tidak dapat meneruskan objek kueri atau apa pun sebagai argumen kedua.

Bagaimana Anda mengubah url dari /shop/Clothes/dressesmenjadi /shop/Clothes/dresses?color=bluedi react-router tanpa menggunakan <Link>?

Dan apakah suatu onChangefungsi benar-benar satu-satunya cara untuk mendengarkan perubahan kueri? Mengapa perubahan kueri tidak secara otomatis terdeteksi dan bereaksi terhadap perubahan parameter?

claireablani.dll
sumber
Anda harus menggunakan singleton sejarah sebagaimana yang dirujuk dalam pertanyaan ini
Joseph Combs

Jawaban:

143

Di dalam pushmetode hashHistory, Anda dapat menentukan parameter kueri Anda. Misalnya,

history.push({
  pathname: '/dresses',
  search: '?color=blue'
})

atau

history.push('/dresses?color=blue')

Anda dapat melihat repositori ini untuk contoh tambahan tentang penggunaanhistory

John F.
sumber
2
luar biasa! Apakah tetap ada cara untuk meneruskan objek kueri {color: blue, size: 10} alih-alih string?
claireablani
1
@claireablani Saat ini, saya rasa itu tidak didukung
John F.
1
@claireablani Anda bisa mencoba inirouter.push({ pathname: '/path', state: { color: 'blue', size: 10 }, });
MichelH
4
Hanya untuk klarifikasi, ini tidak lagi berfungsi di react router v4. Untuk itu, lihat jawaban @ kristupas-repečka
dkniffin
14
saat-saat tidak stabil yang kita jalani.
Kristupas Repečka
39

Contoh menggunakan paket react-router v4, redux-thunk dan react-router-redux (5.0.0-alpha.6).

Ketika pengguna menggunakan fitur pencarian, saya ingin dia dapat mengirim tautan url untuk permintaan yang sama ke rekan kerja.

import { push } from 'react-router-redux';
import qs from 'query-string';

export const search = () => (dispatch) => {
    const query = { firstName: 'John', lastName: 'Doe' };

    //API call to retrieve records
    //...

    const searchString = qs.stringify(query);

    dispatch(push({
        search: searchString
    }))
}
Kristupas Repečka
sumber
8
react-router-reduxtidak digunakan lagi
vsync
Saya pikir ini sekarang harus dilakukan dengan merender <Redirect>tag, tautan ke halaman dokumen
TKAB
2
Anda bisa membungkus komponen Anda di withReducerHOC yang akan memberi Anda historyprop. Dan kemudian Anda bisa lari history.push({ search: querystring }.
sasklacz
Sebagai gantinya react-router-redux, Anda dapat menggunakan connected-react-routeryang sudah tidak digunakan lagi.
Søren Boisen
29

Jawaban John benar. Ketika saya berurusan dengan params, saya juga membutuhkan URLSearchParamsantarmuka:

this.props.history.push({
    pathname: '/client',
    search: "?" + new URLSearchParams({clientId: clientId}).toString()
})

Anda mungkin juga perlu membungkus komponen Anda dengan withRouterHOC misalnya. export default withRouter(YourComponent);.

spedy
sumber
1
withRouteradalah HOC, bukan dekorator
Luis Paulo
4
    for react-router v4.3, 
 const addQuery = (key, value) => {
  let pathname = props.location.pathname; 
 // returns path: '/app/books'
  let searchParams = new URLSearchParams(props.location.search); 
 // returns the existing query string: '?type=fiction&author=fahid'
  searchParams.set(key, value);
  this.props.history.push({
           pathname: pathname,
           search: searchParams.toString()
     });
 };

  const removeQuery = (key) => {
  let pathname = props.location.pathname; 
 // returns path: '/app/books'
  let searchParams = new URLSearchParams(props.location.search); 
 // returns the existing query string: '?type=fiction&author=fahid'
  searchParams.delete(key);
  this.props.history.push({
           pathname: pathname,
           search: searchParams.toString()
     });
 };


 ```

 ```
 function SomeComponent({ location }) {
   return <div>
     <button onClick={ () => addQuery('book', 'react')}>search react books</button>
     <button onClick={ () => removeQuery('book')}>remove search</button>
   </div>;
 }
 ```


 //  To know more on URLSearchParams from 
[Mozilla:][1]

 var paramsString = "q=URLUtils.searchParams&topic=api";
 var searchParams = new URLSearchParams(paramsString);

 //Iterate the search parameters.
 for (let p of searchParams) {
   console.log(p);
 }

 searchParams.has("topic") === true; // true
 searchParams.get("topic") === "api"; // true
 searchParams.getAll("topic"); // ["api"]
 searchParams.get("foo") === null; // true
 searchParams.append("topic", "webdev");
 searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"
 searchParams.set("topic", "More webdev");
 searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev"
 searchParams.delete("topic");
 searchParams.toString(); // "q=URLUtils.searchParams"


[1]: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
Fahid M
sumber
3

Dari DimitriDushkin di GitHub :

import { browserHistory } from 'react-router';

/**
 * @param {Object} query
 */
export const addQuery = (query) => {
  const location = Object.assign({}, browserHistory.getCurrentLocation());

  Object.assign(location.query, query);
  // or simple replace location.query if you want to completely change params

  browserHistory.push(location);
};

/**
 * @param {...String} queryNames
 */
export const removeQuery = (...queryNames) => {
  const location = Object.assign({}, browserHistory.getCurrentLocation());
  queryNames.forEach(q => delete location.query[q]);
  browserHistory.push(location);
};

atau

import { withRouter } from 'react-router';
import { addQuery, removeQuery } from '../../utils/utils-router';

function SomeComponent({ location }) {
  return <div style={{ backgroundColor: location.query.paintRed ? '#f00' : '#fff' }}>
    <button onClick={ () => addQuery({ paintRed: 1 })}>Paint red</button>
    <button onClick={ () => removeQuery('paintRed')}>Paint white</button>
  </div>;
}

export default withRouter(SomeComponent);
Desain oleh Adrian
sumber
2

Menggunakan modul query-string adalah yang disarankan saat Anda membutuhkan modul untuk mengurai string kueri Anda dengan mudah.

http: // localhost: 3000? token = xxx-xxx-xxx

componentWillMount() {
    var query = queryString.parse(this.props.location.search);
    if (query.token) {
        window.localStorage.setItem("jwt", query.token);
        store.dispatch(push("/"));
    }
}

Di sini, saya mengarahkan kembali ke klien saya dari server Node.js setelah otentikasi Google-Passport berhasil, yang mengalihkan kembali dengan token sebagai parameter kueri.

Saya menguraikannya dengan modul kueri-string, menyimpannya dan memperbarui parameter kueri di url dengan push dari react-router-redux .

Balasubramani M
sumber
1

Saya lebih suka Anda menggunakan fungsi di bawah ini yaitu ES6gaya:

getQueryStringParams = query => {
    return query
        ? (/^[?#]/.test(query) ? query.slice(1) : query)
            .split('&')
            .reduce((params, param) => {
                    let [key, value] = param.split('=');
                    params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
                    return params;
                }, {}
            )
        : {}
};
AmerllicA
sumber
1

Itu juga bisa ditulis seperti ini

this.props.history.push(`${window.location.pathname}&page=${pageNumber}`)
madhu131313
sumber