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>
Franco
fonte
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.

cristão
fonte
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.

spencer.sm
fonte
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 .

nbeuchat
fonte
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
MING WU
fonte
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'}
JTG
fonte
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');
t-reksio
fonte
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
1
URLSearchParams Não é suportado pelo IE developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/…
Michael Freidgeim
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

Mike Frenil L
fonte
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
TommyLike
fonte
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>;
}
dsgriffin
fonte
17

Se o seu roteador for assim

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

Você receberá esse ID assim

this.props.match.params.id
Milan Panigrahi
fonte
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
14

Com este one-liner, você pode usá-lo em qualquer lugar no React Hook e no React Class Component com JavaScript simples.

https://www.hunterisgod.com/?city=Leipzig

let city = (new URLSearchParams(window.location.search)).get("city")
Caçador
fonte
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))
jtlindsey
fonte
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!

NarDd
fonte
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)
Shubham Khatri
fonte
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
    })
}
Anas Alpure
fonte
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>
  )
}
Ruby Ybur
fonte
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.

nizam.sp
fonte
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)

Rocco Ghielmini
fonte
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

krystianj
fonte
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}));
}
Joe
fonte
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.

Jayant Patil
fonte
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)
}

prabhu
fonte
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'}
kajkal
fonte
-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}
        );
}
Roushan Jha
fonte
-3
let data = new FormData();
data.append('file', values.file);
vírus fatemeh kazemi zadeh3000
fonte
-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 });
      });
  }
AJ
fonte