React - Como obter o valor do parâmetro da string de consulta


412

Como posso definir uma rota no meu arquivo routes.jsx para capturar o __firebase_request_keyvalor do parâmetro de uma URL gerada pelo processo de logon único do Twitter após o redirecionamento de seus servidores?

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

Eu tentei com a seguinte configuração de rotas, mas o :redirectParamnão está capturando o parâmetro mencionado:

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

1
Há uma discussão no Github aqui
vsync

3
lamentável que a questão diz "seqüências de consulta", mas é realmente perguntando sobre "parâmetros de URL"
SeanMC

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

Respostas:


484

React Router v3

O React Router já analisa o local e o transmite ao seu RouteComponent como acessórios. Você pode acessar a parte da consulta (depois? Na url) via

this.props.location.query.__firebase_request_key

Se você estiver procurando pelos valores dos parâmetros do caminho, separados por dois pontos (:) dentro do roteador, eles podem ser acessados ​​via

this.props.match.params.redirectParam

Isso se aplica às versões atrasadas do React Router v3 (não sei qual). As versões mais antigas do roteador foram relatadas para uso this.props.params.redirectParam.

React Router v4 e React Router v5, genéricos

O React Router v4 não analisa mais a consulta, mas você pode acessá-la apenas via this.props.location.search. Por razões, consulte a resposta de nbeuchat .

Por exemplo, com a biblioteca qs importada como qsvocê poderia fazer

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

Outra biblioteca seria a string de consulta . Veja esta resposta para mais algumas idéias sobre a análise da string de pesquisa. Se você não precisa de compatibilidade com o IE, também pode usar

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

Para componentes funcionais, você substituiria this.props.locationpelo gancho useLocation . Observe que você pode usar window.location.search, mas isso não permitirá acionar a renderização do React nas alterações. Se o seu componente (não funcional) não for um filho direto de Switchvocê, será necessário usar o Router para acessar qualquer um dos acessórios fornecidos pelo roteador.

Geral

sugestão de nizam.sp de fazer

console.log(this.props)

será útil em qualquer caso.


3
Não é necessário alterar o roteador de reação para ele.
Christian

2
Eu não sugiro usar console.dir()devido à advertência nota ... pelo menos :)
boldnik

1
Bem, é só olhar o conteúdo uma vez. Você também pode colocar um ponto de interrupção e avaliar this.props no depurador. Atualmente, até o console.log faz o trabalho (pelo menos no Chrome, você pode expandir valores impressos assim) - e até o console.log não é nada para usar na produção.
Christian

1
@ Christian Acabei usando javascript simples. caminho const = window.location.pathname; me dá o URL. Posso então analisá-lo da maneira que preciso. Coloquei isso no evento do ciclo de vida componentWillMount no meu componente React.
Sam

5
Em react-router-domeu tive que usar withRouterpara fazer este trabalho!
Demonofthemist

188

React Router v4

Usando component

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

this.props.match.params.id

O componente é renderizado automaticamente com os props da rota.


Usando render

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

this.props.match.params.id

Os adereços de rota são transmitidos para a função de renderização.


1
Eu tive um problema semelhante ao acessar o query paramsURL atual do meu aplicativo em um componente filho usando o React Router v4. Se você estiver procurando pelo query params, this.props.location.query no React Router 4 foi removido (atualmente usando a v4.1.1). Veja esta resposta: stackoverflow.com/a/43630848/1508105
Alex Johnson

42
Infelizmente, isso não responde à pergunta, pois você não terá necessariamente, /users/?q=...mas poderia ter /user?q=.... Você deve usar o this.props.location.searchReact Router v4 e analisar os resultados sozinho, conforme explicado na minha resposta abaixo.
precisa saber é

Essa é a resposta correta. this.props.location.searchnão existe.
NickJ

@ NickJ: qual versão do React Router você usa?
nbeuchat

126

React Router v3

Com o React Router v3, você pode obter uma string de consulta em this.props.location.search(? Qs1 = naisarg & qs2 = parmar). Por exemplo, com let params = queryString.parse(this.props.location.search), daria{ qs1 : 'naisarg', qs2 : 'parmar'}

React Router v4

Com o React Router v4, this.props.location.queryele não existe mais. Você precisa usar this.props.location.searche analisar os parâmetros de consulta sozinho ou usando um pacote existente, como query-string.

Exemplo

Aqui está um exemplo mínimo usando o React Router v4 e a query-stringbiblioteca.

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

Racional

A equipe do React Router racional para remover a querypropriedade é:

Existem vários pacotes populares que consultam a análise / string de strings de maneira um pouco diferente e cada uma dessas diferenças pode ser a maneira "correta" para alguns usuários e "incorreta" para outros. Se o React Router escolhesse o "certo", isso seria adequado apenas para algumas pessoas. Em seguida, seria necessário adicionar uma maneira para outros usuários substituirem seu pacote preferido de análise de consultas. Não há uso interno da cadeia de pesquisa pelo React Router que exige a análise dos pares de valor-chave, portanto, não é necessário escolher qual deles deve estar "certo".

[...]

A abordagem adotada para a 4.0 é retirar todos os recursos de "pilhas incluídas" e voltar ao roteamento básico. Se você precisar de análise de seqüência de caracteres de consulta ou carregamento assíncrono ou integração com Redux ou algo mais específico, poderá adicioná-lo a uma biblioteca específica para seu caso de uso. Há menos quantidade de itens desnecessários e você pode personalizar as coisas de acordo com suas preferências e necessidades específicas.

Você pode encontrar a discussão completa no GitHub .


1
Funciona perfeitamente. Esta deve ser a resposta aceito como de Verão 2018.
mmla

4
por que você ainda precisa de um lib quando você pode usar URLSearchParams
SuperUberDuper

3
@SuperUberDuper por causa do Edge e iOS Safari - developer.mozilla.org/pt-BR/docs/Web/API/…
Brian Burns

3
Claro, mas basta usar o polyfill URLSearchParams
Anthony Manning-Franklin

67

Tanto quanto eu sei, existem três métodos que você pode fazer isso.

1. use expressão regular para obter a string de consulta.

2.Você pode usar a API do navegador. imagem o URL atual é assim:

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

nós apenas queremos obter 123;

Primeiro

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

Então

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

3. use uma terceira biblioteca chamada 'query-string'. Primeiro instale-o

npm i query-string

Em seguida, importe-o para o arquivo javascript atual:

 import queryString from 'query-string'

O próximo passo é obter 'token' no URL atual, faça o seguinte:

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

Espero que ajude.

Actualizado em 25/02/2019

  1. se o URL atual se parecer com o seguinte:

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

nós definimos uma função para obter os parâmetros:

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

Podemos obter 'ajuda':

getQueryVariable('aid') //160990

URLSearchParams não é suportado pelo IE (se isso for relevante para qualquer pessoa :)
Christian

@Christian Typical IE
Trevor Wood

66

O React Router v4 não possui mais o props.location.query objeto (consulte a discussão no github ). Portanto, a resposta aceita não funcionará para projetos mais recentes.

Uma solução para a v4 é usar uma string de consulta da biblioteca externa para analisar oprops.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
Por alguma razão para me qs.parse resultados em:{'?foo': 'bar'}
Chris

2
@ Chris var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });deve corrigi-lo. Exemplo encontrado aqui: github.com/ljharb/qs
Alan Schapira

38

Ao usar ganchos React, não há acesso ao acesso this.props.location. Para capturar parâmetros de URL, use windowobject.

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

1
Esta é uma resposta maravilhosa. Obrigado.
LukeVenter

Você pode usar "useLocation" em "react-router-dom" em vez do objeto window para obter os mesmos resultados.
Chasmatu 11/02


Além disso, o acesso ao window.location não permitirá disparar a nova renderização do React nas alterações.
Christian

25

React Router v4

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

Observe que atualmente é experimental.

Verifique a compatibilidade do navegador aqui: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility


2
Solução agradável, mas infelizmente o IE não suporta ((
Andrey Patseiko

@AndreyPatseiko há um polyfill para esse github.com/WebReflection/url-search-params
Earlee

23

você pode verificar o react-router , de forma simples, pode usar o código para obter o parâmetro de consulta desde que você tenha definido no seu roteador:

this.props.params.userId

25
Esta não é a resposta certa no caso do OP. props.paramsé para parâmetros de URL (segmento de URL prefixado com ':' no roteador de reação), props.location.queryarmazena parâmetros de sequência de caracteres de consulta (após o '?') e é o que o OP deseja.
Matthieu Harlé

21

React Router 5.1+

5.1 introduziu vários ganchos como useLocationeuseParams que podem ser úteis aqui.

Exemplo:

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

Então, se visitamos dizer

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

Você poderia recuperá-lo como

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 o seu roteador for assim

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

Você receberá esse ID assim

this.props.match.params.id

Alguém sabe como isso funciona no React Router 5.0.1? this.props.match.params está sempre vazio.
Mark A. Tagliaferro

2
@ MarkA.Tagliaferro O suporte está disponível apenas para componentes sendo renderizados por uma Rota. Se esse não for o caso do seu componente, você poderá acessá-los envolvendo o componente no withRouter HOC.
Jimmy Longley


11

Se você não está recebendo as this.propsrespostas esperadas com base nas outras respostas, pode ser necessário usar 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

Eu tive dificuldade em resolver esse problema. Se nenhuma das opções acima funcionar, você pode tentar fazer isso. Estou usando o aplicativo create-react-app

Exigências

react-router-dom ":" ^ 4.3.1 "

Solução

No local em que o roteador está especificado

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

Adicione o nome do parâmetro que você gostaria de passar assim

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

Na página em que você está renderizando algum / caminho, você pode especificá-lo para visualizar o nome do parâmetro ID da chamada como este

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

No final, para onde você exporta o padrão

export default withRouter(Component);

Lembre-se de incluir a importação

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

Quando console.log (this.props), você seria capaz do que foi passado. Diverta-se!


2
E se você estiver usando o TypeScript, não esqueça de adicionar #RouteComponentProps<{id: number}>
ThunderDev

1
onde você adiciona RouteComponentProps <{id: number}> ??
Choco

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

classe MyClass estende React.PureComponent <Props> {
pfeds

Em componentDidMount (por exemplo), const myId = this.props.match.params.id;
pfeds

7

React routerda v4 em diante não fornece mais o objeto query paramsdiretamente location. A razão de ser

Existem vários pacotes populares que consultam a análise / string de strings de maneira um pouco diferente e cada uma dessas diferenças pode ser a maneira "correta" para alguns usuários e "incorreta" para outros. Se o React Router escolhesse o "certo", isso seria adequado apenas para algumas pessoas. Em seguida, seria necessário adicionar uma maneira para outros usuários substituirem seu pacote preferido de análise de consultas. Não há uso interno da cadeia de pesquisa pelo React Router que exige a análise dos pares de valor-chave, portanto, não é necessário escolher qual deles deve estar "certo".

Tendo incluído isso, faria mais sentido analisar apenas location.search em seus componentes de exibição que estão esperando um objeto de consulta.

Você pode fazer isso genericamente, substituindo o withRouterde react-routercomo

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
Bem-vindo ao Stack Overflow! Por favor, não responda apenas com o código fonte. Tente fornecer uma boa descrição sobre como sua solução funciona. Veja: Como escrevo uma boa resposta? . Obrigado
sןɐunıɔ ןɐ qɐp

1
Provavelmente, obter um 'dado' não está definido no-undef
Tom Stickel

6

Talvez um pouco tarde, mas esse gancho de reação pode ajudá-lo a obter / definir valores na consulta de URL: https://github.com/rudyhuynh/use-url-search-params (escrito por mim).

Funciona com ou sem react-router. Abaixo está um exemplo de código no seu 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>
  )
}

Muito obrigado por fornecer um gancho tão simples, mas ótimo!
chr1s

5

this.props.params.your_param_name vai funcionar.

Esta é a maneira de obter os parâmetros da sua string de consulta.
Por favor, faça console.log(this.props);para explorar todas as possibilidades.


3

No componente em que você precisa acessar os parâmetros, você pode usar

this.props.location.state.from.search

que revelará toda a cadeia de consulta (tudo após o ?sinal)



2

No React Router v4, apenas comRoute é a maneira correta

Você pode obter acesso às propriedades do objeto histórico e à correspondência mais próxima via componente de ordem superior withRouter. O withRouter transmitirá adereços atualizados de correspondência, localização e histórico para o componente agrupado sempre que renderizado.

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

Eu usei um pacote externo chamado query-string para analisar o parâmetro url dessa maneira.

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 você trabalha com a rota de reação dom, ele esvazia o objeto com for match, mas se você executar o código a seguir, ele será usado para o componente es6 e também funcionará diretamente para o componente function

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>

Dessa forma, você pode obter adereços e combinar parâmetros e ID de perfil

Isso funcionou para mim depois de muita pesquisa no componente es6.


1

Ou talvez algo assim?

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

Você pode criar um gancho simples para extrair parâmetros de pesquisa do local atual:

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
}

então você pode usá-lo dentro do seu componente funcional assim:

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

solução mais simples!

no roteamento:

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

no código de reação:

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 });
      });
  }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.