web-dev-qa-db-fra.com

React router v4 redirect when no match

Je suis nouveau sur react-router (et le routage côté client en général), donc je pense peut-être que tout va mal. Désolé d'avance si c'est le cas ...

Fondamentalement, je veux simplement implémenter 3 règles simples:

  • si aucun utilisateur, redirigez vers '/ login'
  • sinon si la route n'existe pas, redirigez vers '/' (root)
  • sinon laisser l'utilisateur aller à l'itinéraire demandé

Je garde la trace de l'utilisateur dans this.state.user. Mon routeur actuel semble suivre les 2 premières règles, mais ne laisse que l'utilisateur authentifié voir la page d'accueil ('/ profile' redirige vers '/') donc je sais que je fais quelque chose de mal mais je ne peux pas comprendre quoi.

 <Router>
    {this.state.user ? (
      <Switch>
        <Route path="/" exact component={Home}/>
        <Route path="/profile" exact component={Profile}/>
        <Route render={() => (<Redirect to="/" />)}/>
      </Switch>
    ) : (
      <Switch>
        <Route path="/login" exact component={Login}/>
        <Route render={() => (<Redirect to="/login" />)}/>
      </Switch>
    )}
 </Router>

Tout conseil est apprécié. Je vous remercie

7
Egor

Pour toute personne arrivant ici qui cherche comment rediriger si aucun des itinéraires ne correspond:

<Switch>
  // ... your routes
  <Route render={() => <Redirect to="/" />} />
</Switch>

Notez que les itinéraires doivent être des enfants directs du <Switch>, par exemple. cela ne fonctionne pas:

<Switch>
  <Fragment>
    // ... your routes
    <Route render={() => <Redirect to="/" />} />
  </Fragment>
</Switch>

(peut-être corrigé dans les versions plus récentes de react-router)

12
GG.

La réponse est simple

<Switch>
  <Route path="/login" exact component={Login}/>
  {!this.state.user && <Redirect to='/login' />}
  <Route path="/" exact component={Home}/>
  <Route path="/profile" exact component={Profile}/>
  <Redirect to="/" />
</Switch>

La principale différence entre le commutateur et le routeur est que le routeur essaiera d'exécuter tous les chemins correspondants et d'ajouter le contenu ensemble, le commutateur s'arrêtera lors de la première correspondance.

Mon application a une approche similaire, mais j'ai encapsulé protégé routé sur un fichier séparé, puis encapsulé le profil utilisateur en tant que HOC

export const App = () => (
  <Switch>
    <Route exact path='/login' component={Login} />
    {!hasToken() && <Redirect to='/login' />}
    <Route path='/' component={ProtectedRoute} />
  </Switch>
)

protectedRoute.js

const ProtectedRoute = ({ userInfo }: Props) => (
  <Layout userInfo={userInfo}>
    <Switch>
      <Route exact path='/a' component={A} />
      <Route exact path='/b' component={B} />
      <Route path='/c' component={C} />
      <Redirect to='/a' />
    </Switch>
  </Layout>
)

export default withUserInfo(ProtectedRoute)
4
Mark Lai

Avez-vous pensé à utiliser un wrapper Route qui vérifie si un utilisateur est nécessaire pour le Route?

const CanHasRouteAccess = ({ component: Component, iHasUser, ...rest }) => {
  return iHasUser ? (
    <Route {...rest} render={props => <Component {...props} />} />
  ) : (
    <Redirect to="/" />
  );
};

Vous pouvez transmettre les accessoires à la Route ou provoquer une redirection vers la page d'accueil lorsqu'il n'y a pas d'utilisateur.

<CanHasRouteAccess
  path="/personal-data"
  exact
  component={Profile}
  iHasUser={Boolean(user)}
  />
2
Ryan