Acabei de substituir react-router
da v3 para a v4.
Mas não sei como navegar programaticamente na função de membro de a Component
. ou seja, na handleClick()
função que deseja navegar /path/some/where
após o processamento de alguns dados. Eu costumava fazer isso:
import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')
Mas não consigo encontrar essas interfaces na v4.
Como posso navegar usando a v4?
reactjs
ecmascript-6
react-router-v4
Colin Witkamp
fonte
fonte
Component
? Por exemplo, dentro das ações de redux.Respostas:
Se você estiver direcionando para ambientes de navegador, precisará usar o
react-router-dom
pacote, em vez dereact-router
. Eles estão seguindo a mesma abordagem que Reagir fez, a fim de separar o núcleo, (react
) eo código de plataforma específica, (react-dom
,react-native
), com a sutil diferença que você não precisa instalar dois pacotes separados, de modo que os pacotes ambiente contêm tudo você precisa. Você pode adicioná-lo ao seu projeto como:yarn add react-router-dom
ou
npm i react-router-dom
A primeira coisa que você precisa fazer é fornecer
<BrowserRouter>
o componente principal como principal no aplicativo.<BrowserRouter>
usa ahistory
API HTML5 e a gerencia para você, para que você não precise se preocupar em instanciar você mesmo e transmiti-lo ao<BrowserRouter>
componente como um suporte (como era necessário nas versões anteriores).Na V4, para navegar programaticamente, é necessário acessar o
history
objeto, disponível através do Reactcontext
, desde que você tenha um componente de<BrowserRouter>
provedor como o principal pai no aplicativo. A biblioteca expõe através do contexto orouter
objeto que ele próprio contémhistory
como uma propriedade. Ahistory
interface oferece vários métodos de navegação, comopush
,replace
egoBack
, entre outros. Você pode verificar a lista completa de propriedades e métodos aqui .Nota importante para usuários Redux / Mobx
Se você estiver usando redux ou mobx como sua biblioteca de gerenciamento de estado em seu aplicativo, poderá ter problemas com componentes que devem reconhecer o local, mas não são renderizados novamente depois de acionar uma atualização de URLIsso está acontecendo porque
react-router
passalocation
para os componentes usando o modelo de contexto.As 2 abordagens para resolver isso são:
<Route />
. Olocation
objeto atual é um dos adereços que a<Route>
passa para o componente que ele renderizawithRouter
componente de ordem superior, que de fato tem o mesmo efeito e injetalocation
como suporteDeixando isso de lado, há quatro maneiras de navegar programaticamente, ordenadas por recomendação:
1.- Usando um
Promove um estilo declarativo. Antes da v4, os<Route>
componente<Route />
componentes eram colocados no topo da hierarquia de componentes, tendo que pensar na estrutura de suas rotas com antecedência. No entanto, agora você pode ter<Route>
componentes em qualquer lugar da sua árvore, permitindo um controle mais preciso da renderização condicional, dependendo da URL.Route
injetamatch
,location
ehistory
como adereços em seu componente. Os métodos de navegação (tais comopush
,replace
,goBack
...) estão disponíveis como as propriedades dohistory
objecto.Existem três maneiras de renderizar algo com a
Route
, usando adcomponent
,render
ouchildren
adereços, mas não use mais de um no mesmoRoute
. A escolha depende do caso de uso, mas basicamente as duas primeiras opções renderizarão seu componente apenas sepath
corresponder ao local da URL, enquanto quechildren
o componente será renderizado se o caminho corresponder ao local ou não (útil para ajustar a interface do usuário com base no URL Coincidindo).Se você quiser personalizar a sua saída de renderização de componente , você precisa envolver sua componente em uma função e usar a
render
opção, a fim de passar para o seu componente quaisquer outros adereços que você deseja, para além dematch
,location
ehistory
. Um exemplo para ilustrar:2.- Usando
withRouter
HoCEsse componente de ordem superior injeta os mesmos adereços que
Route
. No entanto, ele carrega a limitação de que você pode ter apenas 1 HoC por arquivo.3.- Usando um
A renderização de umRedirect
componente<Redirect>
navegará para um novo local. Mas lembre-se de que, por padrão , o local atual é substituído pelo novo, como redirecionamentos do lado do servidor (HTTP 3xx). O novo local é fornecido peloto
prop, que pode ser uma sequência (URL para a qual redirecionar) ou umlocation
objeto. Se você deseja inserir uma nova entrada no histórico , passe também umpush
suporte e defina-o comotrue
4.- Acessando
Um pouco desencorajado porque o contexto ainda é uma API experimental e é provável que quebre / mude em versões futuras do Reactrouter
manualmente através do contextoEscusado será dizer que também existem outros componentes do roteador destinados a ecossistemas que não são navegadores, como o
<NativeRouter>
que replica uma pilha de navegação na memória e tem como alvo a plataforma React Native, disponível através doreact-router-native
pacote.Para qualquer referência adicional, não hesite em dar uma olhada nos documentos oficiais . Há também um vídeo feito por um dos co-autores da biblioteca que fornece uma introdução bastante interessante ao reag-router v4, destacando algumas das principais mudanças.
fonte
withRouter
dereact-router-dom
withRouter
dereact-router-dom
. O history.push muda o url, mas não parece carregar o<Route>
até eu forçar atualizar a página ...<Router>
dentro de um componente React que está decorado@observer
, o que desencadeia esse problema . A solução é ter@withRouter
em cada componente do React.withRouter
é simplesmente um HOC que usa umRoute
sob o capô. O que significa que ele usa apenas três objetos, histórico, correspondência e local . No exemplo acima, parece quepush
é um adereço quewithRouter
adicionariaButtonToNavigate
, mas esse não é o caso.props.history.push
teria que ser usado em seu lugar. Espero que isso ajude outras pessoas um pouco confusas.browserHistory.push('/path/some/where')
apenas parece muito mais simples. Os autores estão tentando desencorajar a programação imperativa, mas às vezes funciona melhor!A maneira mais fácil de fazer isso:
this.props.history.push("/new/url")
Nota:
history
prop
componente-pai from para o componente que deseja chamar a ação, se não estiver disponível.fonte
this.props.history
disponível em seu componente, poderáimport {withRouter} from 'react-router-dom'
e entãoexport default withRouter(MyComponent)
(ouconst MyComponent = withRouter(...)
) e ele inserirá ohistory
item nos acessórios do seu componente.history.push
e atualização gatilho assim como quando clicamos<Link>
Eu tive um problema semelhante ao migrar para o React-Router v4, então tentarei explicar minha solução abaixo.
Por favor, não considere esta resposta como a maneira correta de resolver o problema, imagino que haja uma boa chance de que algo melhor surja à medida que o React Router v4 se tornar mais maduro e sair do beta (ele pode até já existir e eu simplesmente não o descobri) .
Por contexto, tive esse problema porque ocasionalmente uso
Redux-Saga
para alterar programaticamente o objeto de histórico (por exemplo, quando um usuário se autentica com êxito).Nos documentos do React Router, dê uma olhada no
<Router>
componente e você poderá ver que é capaz de transmitir seu próprio objeto de histórico por meio de um suporte. Essa é a essência da solução - fornecemos o objeto de histórico aReact-Router
partir de um módulo global .Passos:
yarn add history
ounpm install history --save
crie um arquivo chamado
history.js
na suaApp.js
pasta de nível (essa era minha preferência)Adicione esse objeto de história ao seu componente Router, desta forma
Ajuste o URL como antes, importando seu objeto de histórico global:
Tudo deve ficar sincronizado agora, e você também tem acesso a uma maneira de definir o objeto histórico programaticamente e não por meio de um componente / contêiner.
fonte
Route
componente.TL; DR:
A resposta simples e declarativa é que você precisa usar
<Redirect to={URL} push={boolean} />
em combinação comsetState()
Exemplo completo aqui . Leia mais aqui .
PS. O exemplo usa inicializadores de propriedades do ES7 + para inicializar o estado. Olhe aqui também, se você estiver interessado.
fonte
history.push()
métodos.Use
useHistory
gancho se você estiver usando componentes de funçãoVocê pode usar o
useHistory
hook para obter ahistory
instância.O
useHistory
gancho fornece acesso à instância do histórico que você pode usar para navegar.Usar
history
propriedade dentro dos componentes da páginaO React Router injeta algumas propriedades, incluindo
history
a página de componentes.Quebrar componentes filho
withRouter
para injetar propriedades do roteadorwithRouter
wrapper injeta propriedades do roteador nos componentes. Por exemplo, você pode usar esse invólucro para injetar o roteador no componente do botão de logout colocado no menu do usuário.fonte
Você também pode simplesmente usar adereços para acessar o objeto de histórico:
this.props.history.push('new_url')
fonte
this.props.history
disponível em seu componente, poderáimport {withRouter} from 'react-router-dom'
e entãoexport default withRouter(MyComponent)
(ouconst MyComponent = withRouter(...)
) e ele inserirá ohistory
item nos acessórios do seu componente.Etapa 1: existe apenas uma coisa para importar na parte superior:
Etapa 2: em sua rota, passe o histórico:
Etapa 3: o histórico é aceito como parte dos acessórios no próximo componente, para que você possa simplesmente:
Isso foi fácil e muito poderoso.
fonte
Isso funciona:
fonte
Minha resposta é semelhante à de Alex . Não sei por que o React-Router tornou isso tão desnecessariamente complicado. Por que devo envolver meu componente com um HoC apenas para ter acesso ao que é essencialmente global?
De qualquer forma, se você der uma olhada em como elas foram implementadas
<BrowserRouter>
, é apenas um pequeno invólucro da história .Podemos extrair esse histórico para importá-lo de qualquer lugar. O truque, no entanto, é que, se você estiver processando no lado do servidor e tentar
import
o módulo de histórico, ele não funcionará porque usa APIs somente do navegador. Mas tudo bem, porque geralmente redirecionamos apenas em resposta a um clique ou outro evento do lado do cliente. Portanto, provavelmente não há problema em falsificá-lo:Com a ajuda do webpack, podemos definir alguns vars para saber em que ambiente estamos:
E agora você pode
De qualquer lugar. Ele retornará um módulo vazio no servidor.
Se você não quiser usar esses vars mágicos, precisará apenas
require
no objeto global onde é necessário (dentro do manipulador de eventos).import
não funcionará porque funciona apenas no nível superior.fonte
Eu acho que o @rgommezz cobre a maioria dos casos menos um que eu acho muito importante.
Isso me permite escrever um serviço simples com ações / chamadas que posso chamar para fazer a navegação de qualquer componente que eu quiser, sem fazer muito HoC em meus componentes ...
Não está claro por que ninguém forneceu essa solução antes. Espero que ajude, e se você encontrar algum problema com isso, entre em contato.
fonte
Estou testando a v4 há alguns dias e estou adorando até agora! Faz sentido depois de um tempo.
Eu também tive a mesma pergunta e achei que lidar com ela da seguinte forma funcionou melhor (e pode até ser como ele se destina). Ele usa state, um operador ternário e
<Redirect>
.No construtor ()
Na renderização ()
No manipulador de cliques ()
Espero que ajude. Avise-se me.
fonte
Eu lutei com isso por um tempo - algo tão simples, mas tão complicado, porque o ReactJS é apenas uma maneira completamente diferente de escrever aplicativos da Web, é muito estranho para nós, pessoas mais velhas!
Eu criei um componente separado para abstrair a bagunça:
Em seguida, adicione-o ao seu
render()
método:fonte
Como não há outra maneira de lidar com esse design horrível, escrevi um componente genérico que usa a abordagem
withRouter
HOC . O exemplo abaixo está agrupando umbutton
elemento, mas você pode alterar para qualquer elemento clicável necessário:Uso:
fonte
Se você não encontrou this.props.history disponível em seu componente, tente este
fonte
Como às vezes eu prefiro alternar rotas por aplicativo e depois por botões, este é um exemplo de trabalho mínimo que funciona para mim:
fonte
Para aqueles que precisam redirecionar antes de inicializar totalmente um roteador usando
React Router
ouReact Router Dom
Você pode fornecer um redirecionamento simplesmente acessando o objeto de histórico e pressionando um novo estado dentro de sua construçãoapp.js
. Considere o seguinte:Aqui, queremos alterar as rotas de saída dependentes de um subdomínio, interagindo com o objeto de histórico antes que o componente seja processado, podemos redirecionar efetivamente enquanto ainda mantemos nossas rotas intactas.
fonte