Comment implémenter des routes authentifiées dans React Router 4?

J’essayais d’implémenter des routes authentifiées, mais j’ai constaté que React Router 4 empêche maintenant cela de fonctionner:

       

L’erreur est:

Attention: vous ne devez pas utiliser et sur le même itinéraire; sera ignoré

Dans ce cas, quelle est la manière correcte de mettre en œuvre cela?

Il apparaît dans docs de react react-router (v4), il suggère quelque chose comme

  
  • Public Page
  • Protected Page

Mais est-il possible d’y parvenir en regroupant un ensemble de routes?


METTRE À JOUR

Ok, après quelques recherches, j’ai trouvé ceci:

 import React, {PropTypes} from "react" import {Route} from "react-router-dom" export default class AuthenticatedRoute extends React.Component { render() { if (!this.props.isLoggedIn) { this.props.redirectToLogin() return null } return  } } AuthenticatedRoute.propTypes = { isLoggedIn: PropTypes.bool.isRequired, component: PropTypes.element, redirectToLogin: PropTypes.func.isRequired } 

Isit correct pour envoyer une action dans render() il se sent mal. Cela ne semble pas vraiment correct avec componentDidMount ou un autre hook non plus?

    Vous allez vouloir utiliser le composant Redirect . Il existe plusieurs approches différentes à ce problème. Voici un article que j’aime bien, avoir un composant authed qui prend un prop authed , puis le rend en fonction de ces accessoires.

     function PrivateRoute ({component: Component, authed, ...rest}) { return (  authed === true ?  : } /> ) } 

    Maintenant, votre Route s peut ressembler à ceci

         

    Si vous êtes encore confus, j’ai écrit ce post qui pourrait vous aider – Routes protégées et authentification avec React Router v4

    Tnx Tyler McGinnis pour la solution. Je fais mon idée de l’idée de Tyler McGinnis.

     const DecisionRoute = ({ trueComponent, falseComponent, decisionFunc, ...rest }) => { return (  ) } 

    Vous pouvez implémenter cela comme ça

      

    decisionFunc juste une fonction qui retourne true ou false

     const redirectStart = props =>  

    installer react-router-dom

    puis créez deux composants l’un pour les utilisateurs valides et d’autres pour les utilisateurs non valides.

    Essayez ceci sur app.js

     import React from 'react'; import { BrowserRouter as Router, Route, Link, Switch, Redirect } from 'react-router-dom'; import ValidUser from "./pages/validUser/validUser"; import InValidUser from "./pages/invalidUser/invalidUser"; const loggedin = false; class App extends React.Component { render() { return (  
    ( loggedin ? ( ) : () )} />
    ) } } export default App;

    Il semble que votre hésitation consiste à créer votre propre composant puis à l’envoyer dans la méthode de rendu? Eh bien, vous pouvez éviter les deux simplement en utilisant la méthode de render du composant . Pas besoin de créer un composant sauf si vous le souhaitez vraiment. Cela peut être aussi simple que ci-dessous. Notez la propagation {...routeProps} en vous assurant de continuer à envoyer les propriétés du composant vers le composant enfant ( dans ce cas).

      { if (!this.props.isLoggedIn) { this.props.redirectToLogin() return null } return  } /> 

    Voir la documentation de rendu du React Router V4

    Si vous souhaitez créer un composant dédié, il semble que vous êtes sur la bonne voie. Étant donné que React Router V4 est un routage purement déclaratif (il est dit dans la description), je ne pense pas que vous allez vous contenter de placer votre code de redirection en dehors du cycle de vie normal des composants. En regardant le code de React Router lui – même , ils effectuent la redirection dans componentWillMount ou componentDidMount selon qu’il s’agit ou non d’un rendu côté serveur. Voici le code ci-dessous, qui est assez simple et peut vous aider à vous sentir plus à l’aise avec l’endroit où placer votre logique de redirection.

     import React, { PropTypes } from 'react' /** * The public API for updating the location programatically * with a component. */ class Redirect extends React.Component { static propTypes = { push: PropTypes.bool, from: PropTypes.ssortingng, to: PropTypes.oneOfType([ PropTypes.ssortingng, PropTypes.object ]) } static defaultProps = { push: false } static contextTypes = { router: PropTypes.shape({ history: PropTypes.shape({ push: PropTypes.func.isRequired, replace: PropTypes.func.isRequired }).isRequired, staticContext: PropTypes.object }).isRequired } isStatic() { return this.context.router && this.context.router.staticContext } componentWillMount() { if (this.isStatic()) this.perform() } componentDidMount() { if (!this.isStatic()) this.perform() } perform() { const { history } = this.context.router const { push, to } = this.props if (push) { history.push(to) } else { history.replace(to) } } render() { return null } } export default Redirect 

    Je sais que ça fait un moment que je travaille sur un paquet npm pour les routes privées et publiques.

    Voici comment faire un itinéraire privé:

      

    Et vous pouvez également créer des routes publiques auxquelles seul un utilisateur non autorisé peut accéder

      

    J’espère que ça aide!

    Basé sur la réponse de @Tyler McGinnis . J’ai adopté une approche différente en utilisant la syntaxe ES6 et les routes nestedes avec des composants encapsulés :

     import React, { cloneElement, Children } from 'react' import { Route, Redirect } from 'react-router-dom' const PrivateRoute = ({ children, authed, ...rest }) =>  authed ? 
    {Children.map(children, child => cloneElement(child, { ...child.props }))}
    : } /> export default PrivateRoute

    Et en l’utilisant:

      

    Il suffit d’append ma solution au problème.

    J’utilise des jetons jwt pour l’authentification, donc si l’utilisateur a ce jeton, je les redirectai vers la page d’accueil ou je les redirectai vers la page de connexion par défaut (qui est cette route ‘/’). Donc, une fois l’utilisateur connecté et essayer d’accéder à la page de connexion (dans mon cas ‘/’). Je les redirectai à la maison par défaut (‘/ home’).

    Et mes composants ont HOC nommée requireAuth pour vérifier si le jeton utilisateur est valide.

     import React, { Component, Fragment } from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom'; //and also import appropriate components //middleware class checkStatus extends React.Component { render() { if(localStorage.getItem('token')){ return (        } />   ) }else{ return (     ) } } } ReactDOM.render(        , document.querySelector('#root') ); 

    J’ai implémenté en utilisant-

      ( this.state.user.isLoggedIn ? () : () )} /> 

    authentifier les accessoires sera transmis aux composants, par exemple, en utilisant quel état d’utilisateur peut être modifié. AppRoutes complet

     import React from 'react'; import { Switch, Route } from 'react-router-dom'; import { Redirect } from 'react-router'; import Home from '../pages/home'; import Login from '../pages/login'; import Signup from '../pages/signup'; import Dashboard from '../pages/dashboard'; import { config } from '../utils/Config'; export default class AppRoutes extends React.Component { constructor(props) { super(props); // initially assuming that user is logged out let user = { isLoggedIn: false } // if user is logged in, his details can be found from local storage try { let userJsonSsortingng = localStorage.getItem(config.localStorageKey); if (userJsonSsortingng) { user = JSON.parse(userJsonSsortingng); } } catch (exception) { } // updating the state this.state = { user: user }; this.authenticate = this.authenticate.bind(this); } // this function is called on login/logout authenticate(user) { this.setState({ user: user }); // updating user's details localStorage.setItem(config.localStorageKey, JSON.ssortingngify(user)); } render() { return (    } />  } />  ( this.state.user.isLoggedIn ? () : () )} />  ); } } 

    Consultez le projet complet ici: https://github.com/varunon9/hello-react