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?

claireablani
la source
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

John F.
la source
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
    }))
}
Kristupas Repečka
la source
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);.

spedy
la source
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
Fahid M
la source
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);
Conception par Adrian
la source
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 .

Balasubramani M
la source
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;
                }, {}
            )
        : {}
};
AmerllicA
la source
1

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

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