Comment mettre à jour par programme les paramètres de requête dans react-router?


117

Je n'arrive pas à trouver comment mettre à jour les paramètres de requête avec react-router sans utiliser <Link/>. hashHistory.push(url)ne semble pas enregistrer les paramètres de requête, et il ne semble pas que vous puissiez passer un objet de requête ou quoi que ce soit comme second argument.

Comment changer l'URL de /shop/Clothes/dressesà /shop/Clothes/dresses?color=bluedans react-router sans utiliser <Link>?

Et une onChangefonction est-elle vraiment le seul moyen d'écouter les changements de requête? Pourquoi les changements de requête ne sont-ils pas automatiquement détectés et réagis à la façon dont les changements de paramètres sont?


vous devriez utiliser le singleton d'histoire comme indiqué dans cette question
Joseph Combs

Réponses:


143

Dans la pushméthode de hashHistory, vous pouvez spécifier vos paramètres de requête. Par exemple,

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

ou

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

Vous pouvez consulter ce référentiel pour des exemples supplémentaires sur l'utilisationhistory


2
impressionnant! Est-il possible de passer un objet de requête {color: blue, size: 10} au lieu d'une chaîne?
claireablani

1
@claireablani Actuellement, je ne pense pas que cela soit pris en charge
John F.

1
@claireablani vous pouvez essayer cecirouter.push({ pathname: '/path', state: { color: 'blue', size: 10 }, });
MichelH

4
Juste pour clarifier, cela ne fonctionne plus dans React Router v4. Pour cela, voir la réponse de @ kristupas-repečka
dkniffin

14
temps instables dans
lesquels

39

Exemple d'utilisation des packages react-router v4, redux-thunk et react-router-redux (5.0.0-alpha.6).

Lorsque l'utilisateur utilise la fonction de recherche, je veux qu'il puisse envoyer un lien URL pour la même requête à un collègue.

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
    }))
}

8
react-router-reduxest obsolète
vsync

Je pense que cela doit maintenant être fait en rendant le <Redirect>tag, lien vers la page de documentation
TKAB

2
Vous pouvez simplement envelopper votre composant dans withReducerHOC qui vous donnera l' historyaccessoire. Et puis vous pouvez courir history.push({ search: querystring }.
sasklacz

Au lieu de react-router-redux, vous pouvez utiliser connected-react-routerce qui n'est pas obsolète.
Søren Boisen

29

La réponse de John est correcte. Lorsque je traite des paramètres, j'ai également besoin d'une URLSearchParamsinterface:

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

Vous devrez peut-être également envelopper votre composant avec un withRouterHOC, par exemple. export default withRouter(YourComponent);.


1
withRouterest un HOC, pas un décorateur
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

3

De DimitriDushkin sur 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);
};

ou

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);

2

L'utilisation du module de chaîne de requête est recommandée lorsque vous avez besoin d'un module pour analyser facilement votre chaîne de requête.

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

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

Ici, je redirige vers mon client depuis le serveur Node.js après une authentification réussie de Google-Passport, qui redirige avec le jeton comme paramètre de requête.

Je l'analyse avec le module de chaîne de requête, je l'enregistre et je mets à jour les paramètres de requête dans l'URL avec le push de react-router-redux .


1

Je préfère que vous utilisiez ci-dessous la fonction qui est le ES6style:

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;
                }, {}
            )
        : {}
};

1

Il peut également être écrit de cette façon

this.props.history.push(`${window.location.pathname}&page=${pageNumber}`)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.