52 votes

Naviguer par programme en utilisant react-router

Je développe une application dans laquelle je vérifie si l'utilisateur n'est pas loggedIn je dois afficher le formulaire de connexion, sinon dispatch an action qui changerait l'itinéraire et charger un autre composant. Voici mon code:

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

Comment puis-je atteindre cet objectif car je ne peux pas changer d'état à l'intérieur de la fonction de rendu.

43voto

Shubham Khatri Points 67350

Vu que vous êtes en utilisant react-router v4

Utilisez votre composant avec withRouter et l'utilisation history.push d'accessoires pour changer l'itinéraire. Vous avez besoin de faire usage de l' withRouter seulement lorsque votre composant n'est pas la réception de l' Router d'accessoires, ce qui peut arriver dans le cas où votre composant est imbriqué dans celui de l'enfant d'un composant rendus par le Routeur et que vous n'avez pas passé le Routeur accessoires ou lorsque le composant n'est pas lié au Routeur à tous et c'est rendu comme un composant distinct de l'Routes.

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


export default withRouter(App);

Remarque Importante

Si vous utilisez withRouter à empêcher la mise à jour ne soit bloqué par shouldComponentUpdate, il est important que withRouter encapsule l' composant qui implémente shouldComponentUpdate. Par exemple, lorsque à l'aide de Redux:

// Cela permet de contourner shouldComponentUpdate

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

// Ne fonctionne pas

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

ou vous pouvez utiliser les Rediriger

import {withRouter} from 'react-router';

class App extends React.Component {
     ...
     render() {
         if(isLoggedIn) {
              return <Redirect to="/home"/>
         }
         // return login component
         return <Login />
    }
}

Avec react-router v2 or react-router v3, vous pouvez faire usage de context de changer dynamiquement la route comme

class App extends React.Component {
     ...
     render() {
         if (isLoggedIn) {
             // dispatch an action to change the route
             this.context.router.push('/home');
         }
         // return login component
         return <Login />
    }
}

App.contextTypes = {
    router: React.PropTypes.object.isRequired
}
export default App;

ou de l'utilisation

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

6voto

tgrrr Points 172

Dans react-routeur version 4:

 import React from 'react'
import { BrowserRouter as Router, Route, Redirect} from 'react-router-dom'

const Example = () => (

  if (isLoggedIn) {
    <OtherComponent />

  } else {

    <Router>
      <Redirect push to="/login" />
      <Route path="/login" component={Login}/>
    </Router>

  }
)

const Login = () => (
    <h1>Form Components</h1>
    ...
)

export default Example;
 

4voto

Chris Jaynes Points 1527

Une autre alternative est de gérer cela à l'aide de Thunk de style asynchrone actions (qui sont sûrs/autorisés à avoir des effets secondaires).

Si vous utilisez Thunk, vous pouvez injecter le même history objet dans votre <Router> de composants et de Thunk actions à l'aide de thunk.withExtraArgument, comme ceci:

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(
  <Provider store={store}
    <Router history={history}>
      <Route path="*" component={CatchAll} />
    </Router
  </Provider>,
appDiv)

Ensuite, dans votre action, créateurs, vous aurez un history instance qui est sûr à utiliser avec ReactRouter, de sorte que vous pouvez simplement déclencher régulièrement Redux événement si vous n'êtes pas connecté:

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

Un autre avantage, c'est que l'url est plus facile à manipuler, maintenant, nous pouvons donc mettre rediriger info sur la chaîne de requête, etc.

Vous pouvez essayer encore de faire cette vérification dans votre Rendu méthodes, mais s'il cause des problèmes, vous pourriez envisager de le faire dans componentDidMount, ou ailleurs dans le cycle de vie (bien qu'aussi je comprends le désir de coller avec Apatrides Fonctionnelle Compeonents!)

Vous pouvez toujours utiliser Redux et mapDispatchToProps d'injecter de l'action créateur dans votre comptonent, de sorte que votre composant n'est encore que faiblement connecté pour Redux.

2voto

Quốc Vũ Vy Points 11

Ceci est ma poignée loggedIn . react-router v4

PrivateRoute est autorisé, entrez path si l'utilisateur est connecté et enregistrez le jeton dans localStorge

     function PrivateRoute({ component: Component, ...rest }) {
     return (
        <Route
          {...rest}
          render={props => (localStorage.token) ? <Component {...props} /> : (
            <Redirect
              to={{
                pathname: '/signin',
                state: { from: props.location },
              }}
            />
          )
          }
        />
      );
    }
 

Définir tous les chemins dans votre application ici

 export default (
  <main>
    <Switch>
      <Route exact path="/signin" component={SignIn} />
      <Route exact path="/signup" component={SignUp} />
      <PrivateRoute path="/" component={Home} />
    </Switch>
  </main>
);
 

0voto

Araz Babayev Points 507
render(){ 

    return (
        <div>  
            { this.props.redirect ? <Redirect to="/" /> :'' } 
            <div>
                add here component codes
            </div>
        </div>
    );
} 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X