React-Router: Aucune route non trouvée?

132

Considérer ce qui suit:

var AppRoutes = [
    <Route handler={App} someProp="defaultProp">
        <Route path="/" handler={Page} />
    </Route>,

    <Route  handler={App} someProp="defaultProp">
        <Route path="/" handler={Header} >
            <Route path="/withheader" handler={Page} />
        </Route>
    </Route>,

    <Route handler={App} someProp="defaultProp">
        <Route path=":area" handler={Area} />
        <Route path=":area/:city" handler={Area} />
        <Route path=":area/:city/:locale" handler={Area} />
        <Route path=":area/:city/:locale/:type" handler={Area} />
    </Route>
];

J'ai un modèle d'application, un modèle d'en-tête et un ensemble de routes paramétrées avec le même gestionnaire (dans le modèle d'application). Je veux pouvoir desservir 404 routes lorsque quelque chose n'est pas trouvé. Par exemple, / CA / SanFrancisco doit être trouvé et géré par Area, alors que / SanFranciscoz doit être 404.

Voici comment je teste rapidement les itinéraires.

['', '/', '/withheader', '/SanFranciscoz', '/ca', '/CA', '/CA/SanFrancisco', '/CA/SanFrancisco/LowerHaight', '/CA/SanFrancisco/LowerHaight/condo'].forEach(function(path){
    Router.run(AppRoutes, path, function(Handler, state){
        var output = React.renderToString(<Handler/>);
        console.log(output, '\n');
    });
});

Le problème est que / SanFranciscoz est toujours géré par la page Area, mais je veux qu'il soit 404. De plus, si j'ajoute un NotFoundRoute à la première configuration d'itinéraire, toutes les pages Area 404.

<Route handler={App} someProp="defaultProp">
    <Route path="/" handler={Page} />
    <NotFoundRoute handler={NotFound} />
</Route>,

Qu'est-ce que je fais mal?

Voici un résumé qui peut être téléchargé et expérimenté.

https://gist.github.com/adjavaherian/aa48e78279acddc25315

4m1r
la source
Pour référence future pour les personnes qui se retrouvent à cette question, en dehors de la bonne réponse ci-dessous, lisez cet article . Je l'ai rencontré plus tôt et je pense que cette personne l'explique parfaitement.
Dimitris Damilos

Réponses:

251

DefaultRoute et NotFoundRoute ont été supprimés dans react-router 1.0.0.

Je tiens à souligner que la route par défaut avec l'astérisque doit être la dernière du niveau de hiérarchie actuel pour fonctionner. Sinon, il remplacera toutes les autres routes qui apparaissent après lui dans l'arborescence car il est le premier et correspond à chaque chemin.

Pour react-router 1, 2 et 3

Si vous souhaitez afficher un 404 et conserver le chemin (même fonctionnalité que NotFoundRoute)

<Route path='*' exact={true} component={My404Component} />

Si vous souhaitez afficher une page 404 mais changer l'url (même fonctionnalité que DefaultRoute)

<Route path='/404' component={My404Component} />
<Redirect from='*' to='/404' />

Exemple avec plusieurs niveaux:

<Route path='/' component={Layout} />
    <IndexRoute component={MyComponent} />
    <Route path='/users' component={MyComponent}>
        <Route path='user/:id' component={MyComponent} />
        <Route path='*' component={UsersNotFound} />
    </Route>
    <Route path='/settings' component={MyComponent} />
    <Route path='*' exact={true} component={GenericNotFound} />
</Route>

Pour react-router 4 et 5

Gardez le chemin

<Switch>
    <Route exact path="/users" component={MyComponent} />
    <Route component={GenericNotFound} />
</Switch>

Rediriger vers une autre route (changer l'URL)

<Switch>
    <Route path="/users" component={MyComponent} />
    <Route path="/404" component={GenericNotFound} />
    <Redirect to="/404" />
</Switch>

L'ordre compte!

Janne Annala
la source
si vous avez une application redux, comment faites-vous: <Redirect from='*' to='/home' />dans cette syntaxe:const routes = { component: Main, childRoutes: [ { path: '/', component: Home }, ], indexRoute: { component: Main, }, };
tatsu
1
si vous souhaitez définir des accessoires pour le 404-Compontent, utilisez ce code:<Route render={(props)=> <MyComponent myProp={someVar} {...props} />} />
Marco Weber
Et une page de 500? Comme une page qui est censée se charger mais que l'API donne une erreur. Comment afficher cela au lieu de la page qui a échoué tout en conservant la route?
PixMach
<Redirection vers = "/ 404" /> provoque un dépassement de la profondeur maximale de mise à jour sur react-router-dom 5.0.0. Même si la page 404 se ferme, elle redirige.
MiguelSlv
5
Je n'aime pas utiliser une redirection car elle masque l'URL problématique à l'utilisateur. Cela nécessite également de revenir deux fois pour revenir à la page précédente.
sdgfsdh
39

Dans les versions plus récentes de react-router, vous souhaitez encapsuler les routes dans un Switch qui ne rend que le premier composant correspondant. Sinon, vous verriez plusieurs composants rendus.

Par exemple:

import React from 'react';
import ReactDOM from 'react-dom';
import {
  BrowserRouter as Router,
  Route,
  browserHistory,
  Switch
} from 'react-router-dom';

import App from './app/App';
import Welcome from './app/Welcome';
import NotFound from './app/NotFound';

const Root = () => (
  <Router history={browserHistory}>
    <Switch>
      <Route exact path="/" component={App}/>
      <Route path="/welcome" component={Welcome}/>
      <Route component={NotFound}/>
    </Switch>
  </Router>
);

ReactDOM.render(
  <Root/>,
  document.getElementById('root')
);
metakermit
la source
12
Vous n'avez pas besoin d'inclure path="*"sur l'itinéraire NotFound. Si vous pathl' omettez , la Route correspondra toujours.
chipit24
1
Pour les personnes qui arrivent en retard, @ chipit24 a raison, pour éviter toute confusion, omettez simplement les pathitinéraires inconnus
Altair312
14

Avec la nouvelle version de React Router (qui utilise maintenant 2.0.1), vous pouvez utiliser un astérisque comme chemin pour acheminer tous les «autres chemins».

Cela ressemblerait donc à ceci:

<Route route="/" component={App}>
    <Route path=":area" component={Area}>
        <Route path=":city" component={City} />
        <Route path=":more-stuff" component={MoreStuff} />    
    </Route>
    <Route path="*" component={NotFoundRoute} />
</Route>
Dejakob
la source
10

Cette réponse est pour react-router-4. Vous pouvez encapsuler toutes les routes dans le bloc Switch, qui fonctionne exactement comme l'expression de casse de commutation, et rend le composant avec la première route correspondante. par exemple)

<Switch>
      <Route path="/" component={home}/>
      <Route path="/home" component={home}/>
      <Route component={GenericNotFound}/> {/* The Default not found component */}
</Switch>

Quand utiliser exact

Sans exact:

<Route path='/home'
       component = {Home} />

{/* This will also work for cases like https://<domain>/home/anyvalue. */}

Avec exact:

<Route exact path='/home'
       component = {Home} />

{/* 
     This will NOT work for cases like https://<domain>/home/anyvalue. 
     Only for https://<url>/home and https://<domain>/home/
*/}

Maintenant, si vous acceptez des paramètres de routage, et si cela s'avère incorrect, vous pouvez le gérer dans le composant cible lui-même. par exemple)

<Route exact path='/user/:email'
       render = { (props) => <ProfilePage {...props} user={this.state.user} />} />

Maintenant dans ProfilePage.js

if(this.props.match.params.email != desiredValue)
{
   <Redirect to="/notFound" component = {GenericNotFound}/>
   //Or you can show some other component here itself.
}

Pour plus de détails, vous pouvez passer par ce code:

App.js

ProfilePage.js

Pranche Tiwari
la source
6

Selon la documentation , l'itinéraire a été trouvé, même si la ressource ne l'a pas été.

Remarque : Ceci n'est pas destiné à être utilisé lorsqu'une ressource n'est pas trouvée. Il existe une différence entre le routeur ne trouvant pas de chemin correspondant et une URL valide qui entraîne une ressource introuvable. L'url courses / 123 est une URL valide et aboutit à un itinéraire correspondant, donc elle a été "trouvée" en ce qui concerne le routage. Ensuite, si nous récupérons des données et découvrons que le cours 123 n'existe pas, nous ne voulons pas passer à un nouvel itinéraire. Tout comme sur le serveur, vous allez de l'avant et servez l'URL mais affichez une interface utilisateur différente (et utilisez un code d'état différent). Vous ne devriez jamais essayer de passer à un NotFoundRoute.

Ainsi, vous pouvez toujours ajouter une ligne dans l' Router.run()avant React.render()pour vérifier si la ressource est valide. HandlerPassez simplement un accessoire au composant ou remplacez le composant par un personnalisé pour afficher la vue NotFound.

Brad B
la source
merci @brad, vous avez raison, vous devez gérer cela avec le composant et / ou remplacer le gestionnaire avant router.run
4m1r
3
NotFound était obsolète github.com/reactjs/react-router/releases/tag/v1.0.0 , utilisez maintenant <Route path="*" to="/dest" />ou <Redirect from="*" to="/dest" />comme dernière sous-route à correspondre, je crois
ptim
5

Je viens de jeter un coup d'œil à votre exemple, mais si je l'ai bien compris, vous essayez d'ajouter 404 routes à des segments dynamiques. J'ai eu le même problème il y a quelques jours, j'ai trouvé # 458 et # 1103 et j'ai fini avec une vérification faite à la main dans la fonction de rendu:

if (!place) return <NotFound />;

J'espère que cela pourra aider!

Jörn
la source
merci @jorn, je pense que vous avez raison, cela ne semble adressable qu'au niveau des composants
4m1r