React - Come ottenere il valore del parametro dalla stringa di query


412

Come posso definire una route nel mio file trails.jsx per acquisire il __firebase_request_keyvalore del parametro da un URL generato dal processo di accesso singolo di Twitter dopo il reindirizzamento dai loro server?

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

Ho provato con la seguente configurazione di route, ma :redirectParamnon sta rilevando il parametro menzionato:

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

1
C'è una discussione su Github qui
vsync,

3
sfortunato che la domanda dice "stringhe di query" ma in realtà si chiede "parametri url"
SeanMC

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

Risposte:


484

React Router v3

React Router analizza già la posizione per te e la passa al tuo RouteComponent come oggetti di scena. È possibile accedere alla parte della query (dopo? Nell'url) tramite

this.props.location.query.__firebase_request_key

Se stai cercando i valori dei parametri del percorso, separati da due punti (:) all'interno del router, questi sono accessibili tramite

this.props.match.params.redirectParam

Questo vale per le ultime versioni di React Router v3 (non sono sicuro di quale). È stato segnalato l'uso di versioni precedenti del router this.props.params.redirectParam.

React Router v4 e React Router v5, generico

React Router v4 non analizza più la query per te, ma puoi accedervi solo tramite this.props.location.search. Per ragioni vedi la risposta di nbeuchat .

Ad esempio con la libreria qs importata come qssi potrebbe fare

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

Un'altra libreria sarebbe query-string . Vedi questa risposta per qualche altra idea sull'analisi della stringa di ricerca. Se non hai bisogno della compatibilità con IE, puoi anche usare

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

Per i componenti funzionali è necessario sostituire this.props.locationcon l'uncino useLocation . Si noti che è possibile utilizzare window.location.search, ma ciò non consente di attivare il rendering React sulle modifiche. Se il componente (non funzionale) non è figlio diretto di un Switchutente, è necessario utilizzare withRouter per accedere a uno dei puntelli del router forniti.

Generale

Il suggerimento di nizam.sp da fare

console.log(this.props)

sarà utile in ogni caso.


3
Non è necessario cambiare il router di reazione per questo.
Christian,

2
Non consiglierei di usarlo a console.dir()causa della nota di avvertimento ... almeno :)
boldnik

1
Bene, è solo per guardare il contenuto, una volta. Puoi anche solo mettere un punto di interruzione e valutare this.props nel debugger. Al giorno d'oggi, anche console.log farà il lavoro (almeno in Chrome è possibile espandere i valori stampati in quel modo) - e persino console.log non è nulla da usare in produzione.
Christian,

1
@Christian Ho finito per usare semplicemente javascript. const path = window.location.pathname; mi dà l'URL. Posso quindi analizzarlo nel modo in cui ho bisogno. L'ho inserito nell'evento del ciclo di vita di componentWillMount nel mio componente React.
Sam,

5
In react-router-domho dovuto usare withRouterper far funzionare questo!
demonofthemist,

188

React Router v4

utilizzando component

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

this.props.match.params.id

Il componente viene reso automaticamente con i puntelli del percorso.


utilizzando render

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

this.props.match.params.id

I puntelli del percorso vengono passati alla funzione di rendering.


1
Ho avuto un problema simile durante l'accesso query paramsall'URL corrente della mia app in un componente figlio utilizzando React Router v4. Se stai cercando query params, this.props.location.query in React Router 4 è stato rimosso (attualmente usando v4.1.1). Vedi questa risposta: stackoverflow.com/a/43630848/1508105
Alex Johnson

42
Questo non risponde alla domanda, sfortunatamente, come non è necessario, /users/?q=...ma si potrebbe avere /user?q=.... Dovresti usare this.props.location.searchReact Router v4 e analizzare i risultati tu stesso come spiegato nella mia risposta di seguito.
Nbeuchat,

Questa è la risposta corretta this.props.location.searchnon esiste.
NickJ

@NickJ: quale versione di React Router usi?
nbeuchat,

126

React Router v3

Con React Router v3, è possibile ottenere una stringa di query da this.props.location.search(? Qs1 = naisarg & qs2 = parmar). Ad esempio, con let params = queryString.parse(this.props.location.search), darebbe{ qs1 : 'naisarg', qs2 : 'parmar'}

React Router v4

Con React Router v4, il this.props.location.querynon esiste più. È necessario utilizzare this.props.location.searchinvece e analizzare i parametri della query da soli o utilizzando un pacchetto esistente come query-string.

Esempio

Ecco un esempio minimo usando React Router v4 e la query-stringlibreria.

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

Razionale

Il team di React Router razionale per rimuovere la queryproprietà è:

Esistono numerosi pacchetti popolari che eseguono query su analisi / stringhe di stringhe in modo leggermente diverso e ognuna di queste differenze potrebbe essere il modo "corretto" per alcuni utenti e "errato" per altri. Se React Router scegliesse quello "giusto", sarebbe giusto solo per alcune persone. Quindi, dovrebbe aggiungere un modo per gli altri utenti di sostituire il loro pacchetto di analisi delle query preferito. Non vi è alcun uso interno della stringa di ricerca da parte di React Router che richiede che analizzi le coppie chiave-valore, quindi non è necessario scegliere quale di queste dovrebbe essere "corretta".

[...]

L'approccio adottato per 4.0 è quello di eliminare tutte le funzionalità "batterie incluse" e tornare al routing di base. Se hai bisogno di analisi della stringa di query o caricamento asincrono o integrazione Redux o qualcos'altro molto specifico, puoi aggiungerlo con una libreria specifica per il tuo caso d'uso. Meno cruft è ricco di ciò che non ti serve e puoi personalizzare le cose in base alle tue preferenze e esigenze specifiche.

Puoi trovare la discussione completa su GitHub .


1
Funziona perfettamente. Questa dovrebbe essere la risposta accettata dall'estate 2018.
mmla,

4
perché hai persino bisogno di una lib quando puoi usare URLSearchParams
SuperUberDuper

3
@SuperUberDuper a causa di Edge e iOS Safari - developer.mozilla.org/en-US/docs/Web/API/…
Brian Burns

3
Certo, ma usa semplicemente il polyfill di URLSearchParams
Anthony Manning-Franklin,

67

Per quanto ne so ci sono tre metodi che puoi fare.

1.utilizzare un'espressione regolare per ottenere la stringa di query.

2.È possibile utilizzare l'API del browser. immagine l'URL corrente è così:

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

vogliamo solo ottenere 123;

Primo

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

Poi

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

3. utilizzare una terza libreria chiamata "query-string". Prima installalo

npm i query-string

Quindi importalo nel file javascript corrente:

 import queryString from 'query-string'

Il prossimo passo è ottenere 'token' nell'URL corrente, effettuare le seguenti operazioni:

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

Spero che sia d'aiuto.

Aggiornato il 25/02/2019

  1. se l'URL corrente è simile al seguente:

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

definiamo una funzione per ottenere i parametri:

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

Possiamo ottenere "aiuti" tramite:

getQueryVariable('aid') //160990

URLSearchParams non è supportato da IE (se questo è rilevante per chiunque :)
Christian il

@Christian Typical IE
Trevor Wood

66

React Router v4 non ha più l' props.location.query oggetto (vedi la discussione su github ). Quindi la risposta accettata non funzionerà per i progetti più recenti.

Una soluzione per v4 consiste nell'utilizzare una stringa di query della libreria esterna per analizzare il fileprops.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
Per qualche motivo per me qs.parse risulta in:{'?foo': 'bar'}
Chris

2
@Chris var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });dovrebbe risolverlo. Esempio trovato qui: github.com/ljharb/qs
Alan Schapira,

38

Quando si utilizzano gli hook React non è possibile accedere this.props.location. Per acquisire i parametri dell'URL usa l' windowoggetto.

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

1
Questa è una risposta meravigliosa Grazie.
LukeVenter il

È possibile utilizzare "useLocation" da "reazioni-router-dom" anziché dall'oggetto finestra per ottenere gli stessi risultati.
Chasmatu l'


Inoltre, l'accesso a window.location non consentirà di attivare il nuovo rendering di React sulle modifiche.
Christian

25

React Router v4

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

Si prega di notare che è attualmente sperimentale.

Controlla la compatibilità del browser qui: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility


2
Bella soluzione ma sfortunatamente IE non supporta ((
Andrey Patseiko

@AndreyPatseiko c'è un polyfill per quel github.com/WebReflection/url-search-params
Earlee

23

puoi controllare il reagente-router , in parole povere, puoi usare il codice per ottenere il parametro di query fintanto che hai definito nel tuo router:

this.props.params.userId

25
Questa non è la risposta giusta nel caso di OP. props.paramsè per i parametri URL (segmento dell'URL con il prefisso ":" nel router di reazione), props.location.querymemorizza i parametri della stringa di query (dopo "?") ed è ciò che OP desidera.
Matthieu Harlé,

21

React Router 5.1+

5.1 ha introdotto vari ganci come useLocationeuseParams che potrebbero essere utili qui.

Esempio:

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

Quindi se abbiamo visitato dire

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

Potresti recuperarlo come

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

Se il tuo router è così

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

Otterrai quell'ID in questo modo

this.props.match.params.id

Qualcuno sa come funziona in React Router 5.0.1? this.props.match.params è sempre vuoto.
Mark A. Tagliaferro,

2
@ MarkA.Tagliaferro L'elica è disponibile solo per i componenti resi da una Route. In caso contrario, è possibile accedervi avvolgendo il componente nell'HOC withRouter.
Jimmy Longley,


11

Se non ricevi il this.props... ti aspettavi in ​​base alle altre risposte, potresti dover usare 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

Ho avuto difficoltà a risolvere questo problema. Se nessuna delle precedenti funzioni funziona, puoi provare questo. Sto usando l'app create-reagire

Requisiti

reazioni-router-dom ":" ^ 4.3.1 "

Soluzione

Nel punto in cui è specificato il router

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

Aggiungi il nome del parametro che vorresti passare in questo modo

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

Nella pagina in cui si sta eseguendo il rendering di alcuni / percorso è possibile specificare questo per visualizzare l'id di chiamata del nome del parametro in questo modo

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

Alla fine, dove esporti predefinito

export default withRouter(Component);

Ricorda di includere l'importazione

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

Quando console.log (this.props) sarai in grado di sapere cosa è stato tramandato. Divertiti!


2
E se usi TypeScript non dimenticare di aggiungereRouteComponentProps<{id: number}>
ThunderDev,

1
dove aggiungi RouteComponentProps <{id: number}> ??
Choco,

type Props = RouteComponentProps <{id: number}>;
pfeds il

classe MyClass estende React.PureComponent <Props> {
pfeds il

Quindi in componentDidMount (ad esempio), const myId = this.props.match.params.id;
pfeds il

7

React routerdalla v4 in poi non ti dà più query paramsdirettamente nel suo locationoggetto. Il motivo è

Esistono numerosi pacchetti popolari che eseguono query su analisi / stringhe di stringhe in modo leggermente diverso e ognuna di queste differenze potrebbe essere il modo "corretto" per alcuni utenti e "errato" per altri. Se React Router scegliesse quello "giusto", sarebbe giusto solo per alcune persone. Quindi, dovrebbe aggiungere un modo per gli altri utenti di sostituire il loro pacchetto di analisi delle query preferito. Non vi è alcun uso interno della stringa di ricerca da parte di React Router che richiede che analizzi le coppie chiave-valore, quindi non è necessario scegliere quale di queste dovrebbe essere "corretta".

Detto ciò, sarebbe più sensato analizzare solo location.search nei componenti della vista che prevedono un oggetto query.

È possibile farlo genericamente sovrascrivendo il withRouterda react-routercome

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
Benvenuto in Stack Overflow! Per favore, non rispondere solo con il codice sorgente. Prova a fornire una bella descrizione del funzionamento della tua soluzione. Vedi: Come posso scrivere una buona risposta? . Grazie
sɐunıɔ ןɐ qɐp

1
Probabilmente andando a ottenere un 'dato' non è definito no-undef
Tom Stickel

6

Forse un po 'in ritardo ma questo hook di reazione può aiutarti a ottenere / impostare i valori nella query URL: https://github.com/rudyhuynh/use-url-search-params (scritto da me).

Funziona con o senza react-router. Di seguito è riportato un esempio di codice nel tuo caso:

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

Grazie mille per aver fornito un gancio così semplice ma eccezionale!
chr1s

5

this.props.params.your_param_name funzionerà.

Questo è il modo per ottenere i parametri dalla stringa di query.
Si prega di fare console.log(this.props);per esplorare tutte le possibilità.


3

Nel componente in cui è necessario accedere ai parametri che è possibile utilizzare

this.props.location.state.from.search

che rivelerà l'intera stringa di query (tutto dopo il ?segno)



2

In React Router v4 solo con Route è il modo corretto

È possibile accedere alle proprietà dell'oggetto storico e alla corrispondenza più vicina tramite il componente di ordine superiore withRouter. withRouter passerà gli oggetti di corrispondenza, posizione e cronologia aggiornati al componente spostato ogni volta che viene eseguito il rendering.

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

Ho usato un pacchetto esterno chiamato query-string per analizzare il parametro url in questo modo.

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

Quando lavori con la route di reazione dom allora svuota l'oggetto con for match ma se fai il seguente codice lo farà per il componente es6 e funziona direttamente per il componente della funzione

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>

In questo modo puoi ottenere oggetti di scena e abbinare parametri e ID profilo

Questo ha funzionato per me dopo molte ricerche sul componente es6.


1

O forse qualcosa del genere?

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

È possibile creare un hook semplice per estrarre i parametri di ricerca dalla posizione corrente:

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
}

allora potresti usarlo all'interno del tuo componente funzionale in questo modo:

// 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

soluzione più semplice!

nel routing:

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

nel codice di reazione:

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 });
      });
  }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.