Como passar parâmetros com history.push / Link / Redirect no react-router v4?

216

Como podemos passar parâmetros this.props.history.push('/page')no React-Router v4?

.then(response => {
       var r = this;
        if (response.status >= 200 && response.status < 300) {
             r.props.history.push('/template');
          });
IshanGarg
fonte
O componente que é processado por um Routedeve ter acesso a this.props.location, this.props.history, etc. Eu acho que você não precisa usar refmais com v4. Tente fazerthis.props.history.push('/template');
saadq 22/17/17
Não é ref, é variável que aponta para isso; this.props.history.push ('/ template'); leve-me para a próxima página, mas eu quero passar adereços com eles .ref = this;
IshanGarg
Você está tentando passar propspara o componente que corresponde à rota? Eu acho que esse segmento do GitHub soluciona sua preocupação.
Saadq 23/05
JFYI - Eu removi <a href> e adicionei <Link>, que também tem a opção de enviar estado, que pode ser acessado na próxima página via this.props.location.state.
Manohar Reddy Poreddy 21/11/19
Você poderia marcar uma das respostas como 'resposta'. Estou certo de que as pessoas que passam o tempo digitando-as irão gostar.
James Poulose 25/03

Respostas:

391

Primeiro de tudo, você não precisa fazer var r = this;isso emif statement se refere ao contexto do retorno de chamada em si, pois, como você está usando a função de seta, refere-se ao contexto do componente React.

De acordo com os documentos:

objetos de histórico geralmente têm as seguintes propriedades e métodos:

  • length - (number) O número de entradas na pilha do histórico
  • action - (string) A ação atual (PUSH, REPLACE ou POP)
  • local - (objeto) O local atual. Pode ter as seguintes propriedades:

    • nome do caminho - (string) O caminho do URL
    • search - (string) A string de consulta do URL
    • hash - (string) O fragmento de hash da URL
    • state - (string) estado específico do local que foi fornecido para, por exemplo, enviar (caminho, estado) quando esse local foi enviado para a pilha. Disponível apenas no histórico do navegador e da memória.
  • push (caminho, [estado]) - (função) Coloca uma nova entrada na pilha de histórico
  • substituir (caminho, [estado]) - (função) Substitui a entrada atual na pilha do histórico
  • go (n) - (função) Move o ponteiro na pilha do histórico por n entradas
  • goBack () - (função) Equivalente a go (-1)
  • goForward () - (função) Equivalente a go (1)
  • bloco (prompt) - (função) Impede a navegação

Portanto, durante a navegação, você pode passar adereços para o objeto histórico, como

this.props.history.push({
  pathname: '/template',
  search: '?query=abc',
  state: { detail: response.data }
})

ou similarmente para o Linkcomponente ou o Redirectcomponente

<Link to={{
      pathname: '/template',
      search: '?query=abc',
      state: { detail: response.data }
    }}> My Link </Link>

e, em seguida, no componente que é renderizado com a /templaterota, você pode acessar os adereços passados ​​como

this.props.location.state.detail

Lembre-se também de que, ao usar objetos de histórico ou localização de objetos, você precisa conectar o componente withRouter.

De acordo com os documentos:

withRouter

Você pode obter acesso às propriedades do objeto histórico e a <Route>'scorrespondência mais próxima por meio do withRoutercomponente de ordem superior. withRouter renderizará novamente seu componente toda vez que a rota for alterada com os mesmos acessórios que a <Route>renderização props: { match, location, history }.

Shubham Khatri
fonte
3
sim, isso funcionou. Mas não sei por que this.props.history.push('/template',response.data)não está trabalhando. De acordo com a documentação de push(path, [state]), você não acha que deve funcionar?
Sanket Patel
1
Obrigado por isso! No meu caso eu só estava passando história diretamente, então eu acessada meu prop via this.props.history.location.state.propName -
Nunchucks
@SanketPatel, você precisa fazer isso this.props.history.push ('/ template', {response: response.data})
Arsalan Ahmed Quershi
É possível abrir a rota em uma nova guia enquanto passa dados na variável de estado ao navegar, você pode passar adereços para o objeto de histórico?
Gaurav Kumar
3
e quanto a goBack ()? ao navegar de volta com goBack (), não consigo ver nenhum dos estados do histórico em props.location ou props.history.location. Navegando para frente com push () funciona bem
MariusB
40

você pode usar,

this.props.history.push("/template", { ...response }) ou this.props.history.push("/template", { response: response })

então você pode acessar os dados analisados ​​do /templatecomponente seguindo o código,

const state = this.props.location.state

Leia mais sobre o React Session History Management

Tenusha Guruge
fonte
Essa lógica funcionou para mim enquanto history.push com back_url no estado this.props.history.push (redirect_url, {back_url: '/ needs_url'}); e obtê-lo na página de destino por this.props.location.state.back_url
Braham Dev Yadav
24
  • Para as versões anteriores :

    history.push('/path', yourData);

    E obtenha os dados no componente relacionado, como abaixo:

    this.props.location.state // it is equal to yourData
  • Para as versões mais recentes, a maneira acima funciona bem, mas existe uma nova maneira:

    history.push({
      pathname: '/path',
      customNameData: yourData,
    });

    E obtenha os dados no componente relacionado, como abaixo:

    this.props.location.customNameData // it is equal to yourData

Dica : o statenome da chave foi usado nas versões anteriores e, para versões mais recentes, você pode usar seu nome personalizado para transmitir dados e o uso do statenome não é essencial.

AmerllicA
fonte
compartilhe a referência, que diz que o estado não é essencial, se você o tiver útil
Akshay Vijay Jain
Caro @AkshayVijayJain, é a minha experiência de codificação. Não escrevi essa frase com base em um documento ou referência.
AmerllicA
19

Estendendo a solução (sugerida por Shubham Khatri) para uso com ganchos React (16,8 em diante):

package.json (always worth updating to latest packages)

{
     ...

     "react": "^16.12.0",
     "react-router-dom": "^5.1.2",

     ...
}

Passando parâmetros com histórico de envio:

import { useHistory } from "react-router-dom";

const FirstPage = props => {
    let history = useHistory();

    const someEventHandler = event => {
       history.push({
           pathname: '/secondpage',
           search: '?query=abc',
           state: { detail: 'some_value' }
       });
    };

};

export default FirstPage;

Acessando o parâmetro passado usando useLocation de 'react-router-dom':

import { useEffect } from "react";
import { useLocation } from "react-router-dom";

const SecondPage = props => {
    const location = useLocation();

    useEffect(() => {
       console.log(location.pathname); // result: '/secondpage'
       console.log(location.search); // result: '?query=abc'
       console.log(location.state.detail); // result: 'some_value'
    }, [location]);

};
akhouri
fonte
Muito obrigado, não foi possível encontrar uma alternativa atualizada, exceto a sua resposta!
jamezrin 24/04
10

Se você precisar passar parâmetros de URL

há uma ótima explicação de Tyler McGinnis em seu site, Link para o post

Aqui estão alguns exemplos de código:

  1. no componente history.push:

    this.props.history.push(`/home:${this.state.userID}`)

  2. no componente do roteador, você define a rota:

    <Route path='/home:myKey' component={Home} />

  3. no componente Home:

componentDidMount(){
    const { myKey } = this.props.match.params
    console.log(myKey )
}
shyke
fonte
Eu tenho algo parecido com isto, mas se eu atualizar a página ela trava completamente
rabiaasif
@rabiaasif porque os dados não estão mais lá, você precisa persistir ou armazená-los no armazenamento local
Drew Cordano
3

Não é necessário usar withRouter. Isso funciona para mim:

Na sua página pai,

<BrowserRouter>
   <Switch>
        <Route path="/routeA" render={(props)=> (
          <ComponentA {...props} propDummy={50} />
        )} />

        <Route path="/routeB" render={(props)=> (
          <ComponentB {...props} propWhatever={100} />
          )} /> 
      </Switch>
</BrowserRouter>

Em seguida, no ComponentA ou no ComponentB, você pode acessar

this.props.history

objeto, incluindo o método this.props.history.push.

joedotnot
fonte
Acho que você não precisou withRouterporque envolveu seu componente BrowserRouter, que funciona da mesma forma.
Pie 'Oh' Pah
Sim e você está passando o propsconteúdo para cada componente que inclui o historysuporte.
Jeremy
2

Para usar o React 16.8+ (withHooks), você pode usar desta maneira

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

export default function SomeFunctionalComponent() {
let history = useHistory(); // should be called inside react component

const handleClickButton = () => {    
"funcionAPICALL"
       .then(response => {
             if (response.status >= 200 && response.status < 300) {
                 history.push('/template');
              });
}

return ( <div> Some component stuff 
    <p>To make API POST request and redirect to "/template" click a button API CALL</p>
    <button onClick={handleClickButton}>API CALL<button>
</div>)
} 

Fonte aqui para ler mais https://reacttraining.com/react-router/web/example/auth-workflow

P Mill
fonte
-12

Adicione informações para obter parâmetros de consulta.

const queryParams = new URLSearchParams(this.props.location.search);
console.log('assuming query param is id', queryParams.get('id');

Para mais informações sobre URLSearchParams, verifique este link URLSearchParams

Kamal Pandey
fonte
1
Isso não é de todo relevante para reagir Router 4.
Colby Cox