Wie aktualisiere ich programmgesteuert Abfrageparameter im React-Router?

116

Ich kann anscheinend nicht finden, wie Abfrageparameter mit dem React-Router ohne Verwendung aktualisiert werden können <Link/>. hashHistory.push(url)Es scheint keine Abfrageparameter zu registrieren, und es scheint nicht so, als könnten Sie ein Abfrageobjekt oder etwas anderes als zweites Argument übergeben.

Wie ändere ich die URL von /shop/Clothes/dressesin /shop/Clothes/dresses?color=bluein React-Router ohne zu verwenden <Link>?

Und ist eine onChangeFunktion wirklich die einzige Möglichkeit, auf Änderungen an Abfragen zu warten? Warum werden Abfrageänderungen nicht automatisch erkannt und auf die Parameteränderungen reagiert?

claireablani
quelle
Sie sollten den Geschichts-Singleton verwenden, auf den in dieser Frage
Joseph Combs

Antworten:

141

Innerhalb der pushMethode von hashHistorykönnen Sie Ihre Abfrageparameter angeben. Zum Beispiel,

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

oder

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

In diesem Repository finden Sie weitere Beispiele zur Verwendunghistory

John F.
quelle
2
genial! Gibt es überhaupt eine Möglichkeit, ein Abfrageobjekt {Farbe: Blau, Größe: 10} anstelle einer Zeichenfolge zu übergeben?
Claireablani
1
@ Claireablani Derzeit glaube ich nicht, dass dies unterstützt wird
John F.
1
@ Claireablani Sie könnten dies versuchenrouter.push({ pathname: '/path', state: { color: 'blue', size: 10 }, });
MichelH
4
Nur zur Verdeutlichung funktioniert dies in React Router v4 nicht mehr. Siehe dazu @ kristupas-repečkas Antwort
dkniffin
12
instabile Zeiten, in denen wir leben.
Kristupas Repečka
39

Beispiel mit React-Router v4, Redux-Thunk und React-Router-Redux (5.0.0-alpha.6).

Wenn der Benutzer die Suchfunktion verwendet, möchte er, dass er einen URL-Link für dieselbe Abfrage an einen Kollegen senden kann.

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
quelle
7
react-router-reduxist veraltet
vsync
Ich denke, dies muss jetzt getan werden, indem das <Redirect>Tag gerendert wird , Link zur Dokumentenseite
TKAB
2
Sie können Ihre Komponente einfach in withReducerHOC einwickeln, wodurch Sie die historyRequisite erhalten. Und dann kannst du rennen history.push({ search: querystring }.
Sasklacz
28

Johns Antwort ist richtig. Wenn ich mit Params zu tun habe, brauche ich auch eine URLSearchParamsSchnittstelle:

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

Möglicherweise müssen Sie Ihre Komponente auch mit einem withRouterHOC umschließen, z. export default withRouter(YourComponent);.

spedy
quelle
1
withRouterist ein HOC, kein Dekorateur
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.
quelle
3

Von DimitriDushkin auf 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);
};

oder

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);
Design von Adrian
quelle
2

Die Verwendung des Abfragezeichenfolgenmoduls wird empfohlen, wenn Sie ein Modul benötigen, um Ihre Abfragezeichenfolge einfach zu analysieren.

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("/"));
    }
}

Hier leite ich nach erfolgreicher Google-Passport-Authentifizierung, die mit Token als Abfrageparameter zurückgeleitet wird, vom Node.js-Server zurück zu meinem Client.

Ich analysiere es mit dem Abfragezeichenfolgenmodul, speichere es und aktualisiere die Abfrageparameter in der URL mit Push von React -Router-Redux .

Balasubramani M.
quelle
1

Ich bevorzuge, dass Sie die folgende Funktion verwenden, die ES6Stil ist:

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
quelle
1

Es kann auch so geschrieben werden

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