React-Router: nessun percorso non trovato?


132

Considera quanto segue:

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>
];

Ho un modello di app, un HeaderTemplate e un set di percorsi parametrizzato con lo stesso gestore (all'interno del modello di app). Voglio essere in grado di servire 404 rotte quando qualcosa non viene trovato. Ad esempio, / CA / SanFrancisco dovrebbe essere trovato e gestito da Area, mentre / SanFranciscoz dovrebbe essere 404.

Ecco come testare rapidamente i percorsi.

['', '/', '/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');
    });
});

Il problema è che / SanFranciscoz viene sempre gestito dalla pagina Area, ma voglio che sia 404. Inoltre, se aggiungo NotFoundRoute alla prima configurazione di route, tutte le pagine di Area 404.

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

Che cosa sto facendo di sbagliato?

Ecco una sintesi che può essere scaricata e sperimentata.

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


Per riferimento futuro per le persone che finiscono con questa domanda, oltre alla risposta giusta di seguito, leggi questo articolo . L'ho visto prima e penso che quella persona lo spieghi perfettamente.
Dimitris Damilos

Risposte:


251

DefaultRoute e NotFoundRoute sono stati rimossi in react-router 1.0.0.

Vorrei sottolineare che il percorso predefinito con l'asterisco deve essere l'ultimo nel livello gerarchico corrente per funzionare. Altrimenti sovrascriverà tutte le altre rotte che compaiono dopo di essa nell'albero perché è la prima e corrisponde a ogni percorso.

Per React-Router 1, 2 e 3

Se vuoi visualizzare un 404 e mantenere il percorso (stessa funzionalità di NotFoundRoute)

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

Se si desidera visualizzare una pagina 404 ma modificare l'URL (stessa funzionalità di DefaultRoute)

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

Esempio con più livelli:

<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>

Per i router reattivi 4 e 5

Mantieni il sentiero

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

Reindirizza a un altro percorso (cambia URL)

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

L'ordine è importante!


se hai un'app redux come fai: <Redirect from='*' to='/home' />con questa sintassi:const routes = { component: Main, childRoutes: [ { path: '/', component: Home }, ], indexRoute: { component: Main, }, };
tatsu

1
se vuoi impostare gli oggetti di scena per il componente 404 usa questo codice:<Route render={(props)=> <MyComponent myProp={someVar} {...props} />} />
Marco Weber

Che ne dici di una pagina 500? Come una pagina che dovrebbe essere caricata ma l'API restituisce un errore. Come mostrare questo invece della pagina che non è riuscita mantenendo il percorso?
PixMach

<Redirect to = "/ 404" /> causa il superamento della profondità massima di aggiornamento su react-router-dom 5.0.0. Anche se la pagina 404 esce, reindirizza.
MiguelSlv

5
Non mi piace usare un reindirizzamento perché nasconde l'URL problematico all'utente. Richiede anche di tornare indietro due volte per tornare alla pagina precedente.
sdgfsdh

39

Nelle versioni più recenti di react-router si desidera avvolgere le rotte in uno Switch che esegue il rendering solo del primo componente abbinato. Altrimenti vedresti più componenti renderizzati.

Per esempio:

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')
);

12
Non è necessario includere path="*"nel percorso NotFound. L'omissione pathfarà sì che la rotta corrisponda sempre.
chipit24

1
Per le persone che arrivano in ritardo, @ chipit24 è giusto, per evitare confusione basta omettere del pathtutto per percorsi sconosciuti
Altair312

14

Con la nuova versione di React Router (che ora usa la 2.0.1), puoi usare un asterisco come percorso per instradare tutti gli "altri percorsi".

Quindi sarebbe simile a questo:

<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>

10

Questa risposta è per React-router-4. Puoi racchiudere tutte le rotte nel blocco Switch, che funziona proprio come l'espressione switch-case, ed esegue il rendering del componente con la prima rotta corrispondente. per esempio)

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

Quando usare exact

Senza esatto:

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

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

Con esatto:

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

Ora, se stai accettando i parametri di routing e se risulta errato, puoi gestirlo nel componente di destinazione stesso. per esempio)

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

Ora in ProfilePage.js

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

Per maggiori dettagli puoi leggere questo codice:

App.js

ProfilePage.js


6

Secondo la documentazione , il percorso è stato trovato, anche se la risorsa non lo era.

Nota : non deve essere utilizzato quando una risorsa non viene trovata. Esiste una differenza tra il router che non trova un percorso corrispondente e un URL valido che risulta in una risorsa non trovata. L'url course / 123 è un URL valido e risulta in un percorso corrispondente, quindi è stato "trovato" per quanto riguarda il routing. Quindi, se recuperiamo alcuni dati e scopriamo che il corso 123 non esiste, non vogliamo passare a un nuovo percorso. Proprio come sul server, vai avanti e offri l'URL ma rendi un'interfaccia utente diversa (e usi un codice di stato diverso). Non dovresti mai provare a passare a NotFoundRoute.

Quindi, puoi sempre aggiungere una riga Router.run()prima React.render()per verificare se la risorsa è valida. Basta passare un puntello al componente o sovrascrivere il Handlercomponente con uno personalizzato per visualizzare la vista NotFound.


grazie @brad, hai ragione, devi gestirlo con il componente e / o sovrascrivere il gestore prima del router.run
4m1r

3
NotFound è stato deprecato github.com/reactjs/react-router/releases/tag/v1.0.0 , ora usa <Route path="*" to="/dest" />o <Redirect from="*" to="/dest" />come ultima sub route da abbinare, credo
ptim

5

Ho appena dato una rapida occhiata al tuo esempio, ma se l'ho capito nel modo giusto, stai cercando di aggiungere 404 percorsi a segmenti dinamici. Ho avuto lo stesso problema un paio di giorni fa, ho trovato # 458 e # 1103 e ho finito con un controllo fatto a mano all'interno della funzione di rendering:

if (!place) return <NotFound />;

spero che aiuti!


grazie @jorn, penso che tu abbia ragione, questo sembra indirizzabile solo dal livello dei componenti
4m1r
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.