Programaticamente navegar usando reat-roteador

Estou desenvolvendo uma aplicação em que eu verifiquei se o usuário não está loggedIn tenho que exibir o formulário de login, senão dispatch uma action que mudaria a rota e carregaria outro componente. Aqui está o meu código:

  render() { if (isLoggedIn) { // dispatch an action to change the route } // return login component  } 

Como posso conseguir isso, pois não posso alterar estados dentro da function de renderização.

   

Considerando que você está usando react-router v4

Use o seu componente com o withRouter e use o withRouter de adereços para mudar a rota. Você precisa usar o withRouter somente quando o seu componente não está recebendo os props do Router , isso pode acontecer nos casos em que seu componente é um filho nested de um componente renderizado pelo roteador e você não passou o suporte do roteador para ele ou quando o componente não está vinculado ao roteador e é renderizado como um componente separado das rotas.

 import {withRouter} from 'react-router'; class App extends React.Component { ... componenDidMount() { // get isLoggedIn from localStorage or API call if (isLoggedIn) { // dispatch an action to change the route this.props.history.push('/home'); } } render() { // return login component return  } } export default withRouter(App); 

Nota importante

Se você estiver usando o withRouter para impedir que as atualizações sejam bloqueadas pelo shouldComponentUpdate , é importante que com o withRouter o componente que implementa o shouldComponentUpdate . Por exemplo, ao usar o Redux:

// Isso contorna shouldComponentUpdate

 withRouter(connect(...)(MyComponent)) 

// Isso não

 connect(...)(withRouter(MyComponent)) 

ou você poderia usar o redirecionamento

 import {withRouter} from 'react-router'; class App extends React.Component { ... render() { if(isLoggedIn) { return  } // return login component return  } } 

Com react-router v2 or react-router v3 , pode utilizar o context para alterar dinamicamente a rota como

 class App extends React.Component { ... render() { if (isLoggedIn) { // dispatch an action to change the route this.context.router.push('/home'); } // return login component return  } } App.contextTypes = { router: React.PropTypes.object.isRequired } export default App; 

ou usar

 import { browserHistory } from 'react-router'; browserHistory.push('/some/path'); 

Em react-router versão 4:

 import React from 'react' import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom' const Example = () => ( if (isLoggedIn) {  } else {     } ) const Login = () => ( 

Form Components

... ) export default Example;

Outra alternativa é manipular isso usando ações assíncronas estilo Thunk (que são seguras / permitidas ter efeitos colaterais).

Se você usar Thunk, poderá injetar o mesmo object de history no componente e nas ações Thunk usando thunk.withExtraArgument , desta forma:

 import React from 'react' import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom' import { createBrowserHistory } from "history" import { applyMiddleware, createStore } from "redux" import thunk from "redux-thunk" const history = createBrowserHistory() const middlewares = applyMiddleware(thunk.withExtraArgument({history})) const store = createStore(appReducer, middlewares) render(   , appDiv) 

Em seguida, em seus criadores de ações, você terá uma instância de history que é segura para usar com o ReactRouter, para que você possa acionar um evento regular do Redux se você não estiver logado:

 // meanwhile... in action-creators.js export const notLoggedIn = () => { return (dispatch, getState, {history}) => { history.push(`/login`) } } 

Outra vantagem disso é que a URL é mais fácil de gerenciar, agora, para que possamos inserir informações de redirecionamento na string de consulta, etc.

Você pode tentar ainda fazer essa verificação em seus methods Render, mas se isso causar problemas, você pode considerar fazê-lo em componentDidMount ou em outro lugar no ciclo de vida (embora também eu entenda o desejo de ficar com os Functional Functional Stateless Compeonents!)

Você ainda pode usar o Redux e o mapDispatchToProps para injetar o criador de ações em seu conteúdo, para que seu componente ainda esteja vagamente conectado ao Redux.

 render(){ return ( 
{ this.props.redirect ? :'' }
add here component codes
); }