Reagieren - So erhalten Sie den Parameterwert aus der Abfragezeichenfolge


413

Wie kann ich eine Route in meiner Datei route.jsx definieren, um den __firebase_request_keyParameterwert von einer URL zu erfassen, die vom Single Sign-On-Prozess von Twitter nach der Umleitung von den Servern generiert wurde?

http://localhost:8000/#/signin?_k=v9ifuf&__firebase_request_key=blablabla

Ich habe es mit der folgenden :redirectParamRoutenkonfiguration versucht, aber die fängt den genannten Parameter nicht ab:

<Router>
  <Route path="/" component={Main}>
    <Route path="signin" component={SignIn}>
      <Route path=":redirectParam" component={TwitterSsoButton} />
    </Route>
  </Route>
</Router>

1
Es gibt eine Github Diskussion hier
vsync

3
Leider sagt die Frage "
Abfragezeichenfolgen

6
query strings"? var1 = val & var2 = val2" , url paramters: "/ photos /: companyiD / new"
Maddocks

Antworten:


484

Reagiere auf Router v3

React Router analysiert den Standort bereits für Sie und übergibt ihn als Requisiten an Ihre RouteComponent . Sie können auf den Abfrageteil (nach? In der URL) über zugreifen

this.props.location.query.__firebase_request_key

Wenn Sie nach den Pfadparameterwerten suchen, die im Router durch einen Doppelpunkt (:) getrennt sind, können Sie über diese zugreifen

this.props.match.params.redirectParam

Dies gilt für späte React Router v3-Versionen (nicht sicher, welche). Es wurde berichtet, dass ältere Router-Versionen verwendet werden this.props.params.redirectParam.

React Router v4 und React Router v5, allgemein

React Router v4 analysiert die Abfrage nicht mehr für Sie, sondern kann nur über darauf zugreifen this.props.location.search. Aus Gründen siehe die Antwort von nbeuchat .

ZB mit importierter qs- Bibliothek, wie qsSie es tun könnten

qs.parse(this.props.location.search, { ignoreQueryPrefix: true }).__firebase_request_key

Eine andere Bibliothek wäre eine Abfragezeichenfolge . In dieser Antwort finden Sie weitere Ideen zum Parsen der Suchzeichenfolge. Wenn Sie keine IE-Kompatibilität benötigen , können Sie diese auch verwenden

new URLSearchParams(this.props.location.search).get("__firebase_request_key")

Für Funktionskomponenten würden Sie durch this.props.locationden Hook useLocation ersetzen . Beachten Sie, dass Sie verwenden window.location.searchkönnen, dies ermöglicht jedoch nicht das Auslösen des React-Renderings bei Änderungen. Wenn Ihre (nicht funktionsfähige) Komponente kein direktes untergeordnetes Element von a ist Switch, müssen Sie withRouter verwenden, um auf die vom Router bereitgestellten Requisiten zuzugreifen.

Allgemeines

Vorschlag von nizam.sp zu tun

console.log(this.props)

wird auf jeden Fall hilfreich sein.


3
Es ist nicht erforderlich, den Reaktionsrouter dafür zu ändern.
Christian

2
Ich würde nicht empfehlen, console.dir()wegen Warnhinweis zu verwenden ... zumindest :)
Boldnik

1
Nun, es ist nur einmal zum Betrachten des Inhalts. Sie können auch einfach einen Haltepunkt setzen und this.props im Debugger auswerten. Heutzutage erledigt sogar console.log die Aufgabe (zumindest in Chrome können Sie so gedruckte Werte erweitern) - und selbst console.log ist in der Produktion nicht mehr zu verwenden.
Christian

1
@Christian Am Ende habe ich nur einfaches Javascript verwendet. const path = window.location.pathname; gibt mir die URL. Ich kann es dann so analysieren, wie ich es brauche. Ich habe dies in das Komponentenzyklusereignis componentWillMount in meiner React-Komponente eingefügt.
Sam

5
In musste react-router-domich verwenden withRouter, um diese Arbeit zu machen!
Demonofthemist

188

Reagiere auf Router v4

Verwenden von component

<Route path="/users/:id" component={UserPage}/> 

this.props.match.params.id

Die Komponente wird automatisch mit den Routenrequisiten gerendert.


Verwenden von render

<Route path="/users/:id" render={(props) => <UserPage {...props} />}/> 

this.props.match.params.id

Routenrequisiten werden an die Renderfunktion übergeben.


1
Ich hatte ein ähnliches Problem beim Zugriff auf die query paramsaktuelle URL meiner App in einer untergeordneten Komponente mit React Router v4. Wenn Sie nach der suchen query params, wurde diese.props.location.query in React Router 4 entfernt (derzeit unter Verwendung von v4.1.1). Siehe diese Antwort: stackoverflow.com/a/43630848/1508105
Alex Johnson

41
Dies beantwortet die Frage leider nicht, da Sie nicht unbedingt haben werden, /users/?q=...aber Sie könnten haben /user?q=.... Sie sollten this.props.location.searchReact Router v4 verwenden und die Ergebnisse selbst analysieren, wie in meiner Antwort unten erläutert.
Nbeuchat

Dies ist die richtige Antwort. this.props.location.searchist nicht vorhanden.
NickJ

@ NickJ: Welche Version von React Router verwenden Sie?
Nbeuchat

126

Reagiere auf Router v3

Mit React Router v3 können Sie this.props.location.searchAbfragezeichenfolgen von (? Qs1 = naisarg & qs2 = parmar) abrufen. Zum Beispiel mit let params = queryString.parse(this.props.location.search)würde geben{ qs1 : 'naisarg', qs2 : 'parmar'}

Reagiere auf Router v4

Mit React Router v4 existiert das this.props.location.querynicht mehr. Sie müssen this.props.location.searchstattdessen die Abfrageparameter entweder selbst oder mithilfe eines vorhandenen Pakets wie z query-string.

Beispiel

Hier ist ein minimales Beispiel für die Verwendung von React Router v4 und der query-stringBibliothek.

import { withRouter } from 'react-router-dom';
import queryString from 'query-string';

class ActivateAccount extends Component{
    someFunction(){
        let params = queryString.parse(this.props.location.search)
        ...
    }
    ...
}
export default withRouter(ActivateAccount);

Rational

Das Team des React Routers, das die queryEigenschaft rational entfernt, lautet:

Es gibt eine Reihe gängiger Pakete, die das Parsen / Stringifizieren von Abfragezeichenfolgen etwas anders durchführen, und jeder dieser Unterschiede kann für einige Benutzer die "richtige" und für andere die "falsche" Methode sein. Wenn React Router den "richtigen" auswählen würde, wäre dies nur für einige Leute richtig. Dann müsste es eine Möglichkeit für andere Benutzer geben, in ihrem bevorzugten Abfrage-Parsing-Paket zu ersetzen. Es gibt keine interne Verwendung der Suchzeichenfolge durch React Router, die das Parsen der Schlüssel-Wert-Paare erfordert, sodass nicht ausgewählt werden muss, welche davon "richtig" sein soll.

[...]

Der Ansatz für 4.0 besteht darin, alle Funktionen der "Batterien enthalten" zu entfernen und zum einfachen Routing zurückzukehren. Wenn Sie das Parsen von Abfragezeichenfolgen oder das asynchrone Laden oder die Redux-Integration oder etwas anderes sehr Spezifisches benötigen, können Sie dies mit einer Bibliothek speziell für Ihren Anwendungsfall hinzufügen. Es ist weniger Cruft verpackt, das Sie nicht benötigen, und Sie können die Dinge an Ihre spezifischen Vorlieben und Bedürfnisse anpassen.

Die vollständige Diskussion finden Sie auf GitHub .


1
Funktioniert perfekt. Dies sollte die akzeptierte Antwort ab Sommer 2018 sein.
mmla

4
Warum brauchen Sie überhaupt eine Bibliothek, wenn Sie URLSearchParams
SuperUberDuper

3
@ SuperUberDuper wegen Edge und iOS Safari - developer.mozilla.org/en-US/docs/Web/API/…
Brian Burns

3
Sicher, aber dann verwenden Sie einfach die URLSearchParams-Polyfüllung
Anthony Manning-Franklin

67

Soweit ich weiß, gibt es drei Methoden, mit denen Sie das tun können.

1. Verwenden Sie einen regulären Ausdruck, um die Abfragezeichenfolge abzurufen.

2.Sie können die Browser-API verwenden. Bild die aktuelle URL ist wie folgt:

http://www.google.com.au?token=123

wir wollen nur 123 bekommen;

Zuerst

 const query = new URLSearchParams(this.props.location.search);

Dann

const token = query.get('token')
console.log(token)//123

3. Verwenden Sie eine dritte Bibliothek namens 'query-string'. Installieren Sie es zuerst

npm i query-string

Importieren Sie es dann in die aktuelle Javascript-Datei:

 import queryString from 'query-string'

Der nächste Schritt besteht darin, 'Token' in der aktuellen URL abzurufen. Gehen Sie wie folgt vor:

const value=queryString.parse(this.props.location.search);
const token=value.token;
console.log('token',token)//123

Ich hoffe es hilft.

Aktualisiert am 25/02/2019

  1. wenn die aktuelle URL wie folgt aussieht:

http://www.google.com.au?app=home&act=article&aid=160990

Wir definieren eine Funktion, um die Parameter zu erhalten:

function getQueryVariable(variable)
{
        var query = window.location.search.substring(1);
        console.log(query)//"app=article&act=news_content&aid=160990"
        var vars = query.split("&");
        console.log(vars) //[ 'app=article', 'act=news_content', 'aid=160990' ]
        for (var i=0;i<vars.length;i++) {
                    var pair = vars[i].split("=");
                    console.log(pair)//[ 'app', 'article' ][ 'act', 'news_content' ][ 'aid', '160990' ] 
        if(pair[0] == variable){return pair[1];}
         }
         return(false);
}

Wir können "Hilfe" bekommen durch:

getQueryVariable('aid') //160990

URLSearchParams wird vom IE nicht unterstützt (falls dies für jemanden relevant ist :)
Christian

@Christian Typical IE
Trevor Wood

66

React Router v4 hat das props.location.query Objekt nicht mehr (siehe Github- Diskussion). Die akzeptierte Antwort funktioniert also nicht für neuere Projekte.

Eine Lösung für v4 ist eine externe Bibliothek verwenden Abfrage-String die analysierenprops.location.search

const qs = require('query-string');
//or
import * as qs from 'query-string';

console.log(location.search);
//=> '?foo=bar'

const parsed = qs.parse(location.search);
console.log(parsed);
//=> {foo: 'bar'}

1
Aus irgendeinem Grund führt qs.parse für mich zu:{'?foo': 'bar'}
Chris

2
@ Chris var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });sollte es beheben. Beispiel hier gefunden: github.com/ljharb/qs
Alan Schapira

38

Bei Verwendung von React-Hooks besteht kein Zugriff auf this.props.location. Verwenden Sie windowObjekt, um URL-Parameter zu erfassen .

const search = window.location.search;
const params = new URLSearchParams(search);
const foo = params.get('bar');

1
Dies ist eine wunderbare Antwort. Vielen Dank.
LukeVenter

Sie können "useLocation" von "react-router-dom" anstelle von window object verwenden, um dieselben Ergebnisse zu erzielen.
Chasmatu


Durch den Zugriff auf window.location kann das erneute Rendern von React bei Änderungen nicht ausgelöst werden.
Christian

25

Reagiere auf Router v4

const urlParams = new URLSearchParams(this.props.location.search)
const key = urlParams.get('__firebase_request_key')

Bitte beachten Sie, dass es derzeit experimentell ist.

Überprüfen Sie die Browserkompatibilität hier: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility


2
Schöne Lösung, aber leider unterstützt IE nicht ((
Andrey Patseiko

@AndreyPatseiko gibt es eine Polyfüllung für diesen github.com/WebReflection/url-search-params
Earlee

23

Sie können den React-Router überprüfen. In einfachen Worten können Sie den Code verwenden, um Abfrageparameter abzurufen, solange Sie dies in Ihrem Router definiert haben:

this.props.params.userId

25
Dies ist im Fall von OP nicht die richtige Antwort. props.paramsist für URL-Parameter (URL-Segment mit dem Präfix ':' im Reaktionsrouter), props.location.queryspeichert Abfragezeichenfolgenparameter (nach dem '?') und ist das, was OP will.
Matthieu Harlé

20

Reagiere auf Router 5.1+

5.1 führte verschiedene Haken ein useLocationund useParamsdas könnte hier von Nutzen sein.

Beispiel:

<Route path="/test/:slug" component={Dashboard} />

Dann wenn wir besucht sagen

http://localhost:3000/test/signin?_k=v9ifuf&__firebase_request_key=blablabla

Sie könnten es wie abrufen

import { useLocation } from 'react-router';
import queryString from 'query-string';

const Dashboard: React.FC = React.memo((props) => {
    const location = useLocation();

    console.log(queryString.parse(location.search));

    // {__firebase_request_key: "blablabla", _k: "v9ifuf"}

    ...

    return <p>Example</p>;
}

17

Wenn Ihr Router so ist

<Route exact path="/category/:id" component={ProductList}/>

Sie werden diese ID so bekommen

this.props.match.params.id

Weiß jemand, wie das in React Router 5.0.1 funktioniert? this.props.match.params ist immer leer.
Mark A. Tagliaferro

2
@ MarkA.Tagliaferro Die Requisite ist nur für Komponenten verfügbar, die von einer Route gerendert werden. Wenn dies für Ihre Komponente nicht der Fall ist, können Sie darauf zugreifen, indem Sie Ihre Komponente in das withRouter-HOC einbinden.
Jimmy Longley


11

Wenn Sie nicht die this.props... erhalten, die Sie aufgrund der anderen Antworten erwartet haben, müssen Sie möglicherweise Folgendes verwenden withRouter( docs v4 ):

import React from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router'

// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  }

  render() {
    const { match, location, history } = this.props

    return (
      <div>You are now at {location.pathname}</div>
    )
  }
}

// Create a new component that is "connected" (to borrow redux terminology) to the router.  
const TwitterSsoButton = withRouter(ShowTheLocation)  

// This gets around shouldComponentUpdate
withRouter(connect(...)(MyComponent))

// This does not
connect(...)(withRouter(MyComponent))

8

Es fiel mir schwer, dieses Problem zu lösen. Wenn keine der oben genannten Funktionen funktioniert, können Sie dies stattdessen versuchen. Ich benutze die Create-React-App

Bedarf

React-Router-Dom ":" ^ 4.3.1 "

Lösung

An dem Ort, an dem der Router angegeben ist

<Route path="some/path" ..../>

Fügen Sie den Parameternamen hinzu, den Sie wie folgt übergeben möchten

<Route path="some/path/:id" .../>

Auf der Seite, auf der Sie einige / path rendern, können Sie dies angeben, um die Aufrufnummer des Parameternamens wie folgt anzuzeigen

componentDidMount(){
  console.log(this.props);
  console.log(this.props.match.params.id);
}

Am Ende, wo Sie Standard exportieren

export default withRouter(Component);

Denken Sie daran, den Import einzuschließen

import { withRouter } from 'react-router-dom'

Bei console.log (this.props) können Sie, was weitergegeben wurde. Habe Spaß!


2
Und wenn Sie TypeScript verwenden, vergessen Sie nicht hinzuzufügenRouteComponentProps<{id: number}>
ThunderDev

1
Wo fügst du RouteComponentProps <{id: number}> hinzu?
Choco

Typ Props = RouteComponentProps <{id: number}>;
Pfeds

Klasse MyClass erweitert React.PureComponent <Props> {
pfeds

Dann in componentDidMount (zum Beispiel) const myId = this.props.match.params.id;
Pfeds

7

React routerab v4 gibt man das nicht mehr query paramsdirekt in seinem locationobjekt. Der Grund dafür ist

Es gibt eine Reihe gängiger Pakete, die das Parsen / Stringifizieren von Abfragezeichenfolgen etwas anders ausführen, und jeder dieser Unterschiede kann für einige Benutzer die "richtige" und für andere die "falsche" Methode sein. Wenn React Router den "richtigen" auswählen würde, wäre dies nur für einige Leute richtig. Dann müsste es eine Möglichkeit für andere Benutzer geben, in ihrem bevorzugten Abfrage-Parsing-Paket zu ersetzen. Es gibt keine interne Verwendung der Suchzeichenfolge durch React Router, die das Parsen der Schlüssel-Wert-Paare erfordert, sodass nicht ausgewählt werden muss, welche davon "richtig" sein soll.

Wenn Sie dies aufgenommen haben, ist es nur sinnvoller, location.search in Ihren Ansichtskomponenten zu analysieren, die ein Abfrageobjekt erwarten.

Sie können dies generisch tun, indem Sie das withRouterfrom überschreibenreact-router like

customWithRouter.js

import { compose, withPropsOnChange } from 'recompose';
import { withRouter } from 'react-router';
import queryString from 'query-string';

const propsWithQuery = withPropsOnChange(
    ['location', 'match'],
    ({ location, match }) => {
        return {
            location: {
                ...location,
                query: queryString.parse(location.search)
            },
            match
        };
    }
);

export default compose(withRouter, propsWithQuery)

6
componentDidMount(){
    //http://localhost:3000/service/anas
    //<Route path="/service/:serviceName" component={Service} />
    const {params} =this.props.match;
    this.setState({ 
        title: params.serviceName ,
        content: data.Content
    })
}

4
Willkommen bei Stack Overflow! Bitte antworten Sie nicht nur mit dem Quellcode. Versuchen Sie, eine schöne Beschreibung der Funktionsweise Ihrer Lösung zu geben. Siehe: Wie schreibe ich eine gute Antwort? . Danke
sɐunıɔ ןɐ qɐp

1
Wahrscheinlich wird ein "Daten" nicht no-undef definiert
Tom Stickel

6

Vielleicht etwas spät, aber dieser Reaktions-Hook kann Ihnen helfen, Werte in der URL-Abfrage abzurufen / festzulegen: abzurufen https://github.com/rudyhuynh/use-url-search-params (von mir geschrieben).

Es funktioniert mit oder ohne react-router. Unten finden Sie ein Codebeispiel für Ihren Fall:

import React from "react";
import { useUrlSearchParams } from "use-url-search-params";

const MyComponent = () => {
  const [params, setParams] = useUrlSearchParams()
  return (
    <div>
      __firebase_request_key: {params.__firebase_request_key}
    </div>
  )
}

Vielen Dank für die Bereitstellung eines so einfachen, aber großartigen Hakens!
Chr1s

5

this.props.params.your_param_name wird funktionieren.

Auf diese Weise erhalten Sie die Parameter aus Ihrer Abfragezeichenfolge.
Bitte tun Sie dies console.log(this.props);, um alle Möglichkeiten zu erkunden.


3

In der Komponente, in der Sie auf die Parameter zugreifen müssen, die Sie verwenden können

this.props.location.state.from.search

Dadurch wird die gesamte Abfragezeichenfolge angezeigt (alles nach dem ?Zeichen).



2

In React Router v4 ist nur withRoute richtig

Sie können über die withRouter-Komponente höherer Ordnung auf die Eigenschaften des Verlaufsobjekts und die Übereinstimmung des nächsten zugreifen. withRouter übergibt aktualisierte Übereinstimmungs-, Speicherort- und Verlaufs-Requisiten beim Rendern an die umschlossene Komponente.

import React from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router'

// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  }

  render() {
    const { match, location, history } = this.props

    return (
      <div>You are now at {location.pathname}</div>
    )
  }
}

// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const ShowTheLocationWithRouter = withRouter(ShowTheLocation)

https://reacttraining.com/react-router/web/api/withRouter


2

Ich habe ein externes Paket namens query-string verwendet, um URL-Parameter wie folgt zu analysieren.

import React, {Component} from 'react'
import { parse } from 'query-string';

resetPass() {
    const {password} = this.state;
    this.setState({fetching: true, error: undefined});
    const query = parse(location.search);
    return fetch(settings.urls.update_password, {
        method: 'POST',
        headers: {'Content-Type': 'application/json', 'Authorization': query.token},
        mode: 'cors',
        body: JSON.stringify({password})
    })
        .then(response=>response.json())
        .then(json=>{
            if (json.error)
                throw Error(json.error.message || 'Unknown fetch error');
            this.setState({fetching: false, error: undefined, changePassword: true});
        })
        .catch(error=>this.setState({fetching: false, error: error.message}));
}

2

Wenn Sie mit React Route Dom arbeiten, wird das Objekt für die Übereinstimmung leer. Wenn Sie jedoch den folgenden Code ausführen, gilt dies sowohl für die es6-Komponente als auch direkt für die Funktionskomponente

import { Switch, Route, Link } from "react-router-dom";

<Route path="/profile" exact component={SelectProfile} />
<Route
  path="/profile/:profileId"
  render={props => {
    return <Profile {...props} loading={this.state.loading} />;
  }}
/>
</Switch>
</div>

Auf diese Weise können Sie Requisiten erhalten und Parameter und Profil-IDs abgleichen

Dies funktionierte für mich nach vielen Recherchen zur es6-Komponente.


1

Oder vielleicht so etwas?

let win = {
  'location': {
    'path': 'http://localhost:8000/#/signin?_k=v9ifuf&__firebase_request_key=blablabla'
  }
}
if (win.location.path.match('__firebase_request_key').length) {
  let key = win.location.path.split('__firebase_request_key=')[1]
  console.log(key)
}


0

Sie können einen einfachen Hook zum Extrahieren von Suchparametern aus dem aktuellen Speicherort erstellen:

import React from 'react';
import { useLocation } from 'react-router-dom';

export function useSearchParams<ParamNames extends string[]>(...parameterNames: ParamNames): Record<ParamNames[number], string | null> {
    const { search } = useLocation();
    return React.useMemo(() => { // recalculate only when 'search' or arguments changed
        const searchParams = new URLSearchParams(search);
        return parameterNames.reduce((accumulator, parameterName: ParamNames[number]) => {
            accumulator[ parameterName ] = searchParams.get(parameterName);
            return accumulator;
        }, {} as Record<ParamNames[number], string | null>);
    }, [ search, parameterNames.join(',') ]); // join for sake of reducing array of strings to simple, comparable string
}

dann könnten Sie es in Ihrer Funktionskomponente wie folgt verwenden:

// current url: http://localhost:8000/#/signin?_k=v9ifuf&__firebase_request_key=blablabla
const { __firebase_request_key } = useSearchParams('__firebase_request_key');
// current url: http://localhost:3000/home?b=value
const searchParams = useSearchParameters('a', 'b'); // {a: null, b: 'value'}

-2
export class ClassName extends Component{
      constructor(props){
        super(props);
        this.state = {
          id:parseInt(props.match.params.id,10)
        }
    }
     render(){
        return(
          //Code
          {this.state.id}
        );
}


-5

einfachste Lösung!

im Routing:

   <Route path="/app/someUrl/:id" exact component={binder} />

im Reaktionscode:

componentDidMount() {
    var id = window.location.href.split('/')[window.location.href.split('/').length - 1];
    var queryString = "http://url/api/controller/" + id
    $.getJSON(queryString)
      .then(res => {
        this.setState({ data: res });
      });
  }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.