React-Router: Nie znaleziono trasy?

132

Rozważ następujące:

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

Mam szablon aplikacji, szablon HeaderTemplate i sparametryzowany zestaw tras z tym samym programem obsługi (w szablonie aplikacji). Chcę mieć możliwość obsługi tras 404, gdy czegoś nie znaleziono. Na przykład / CA / SanFrancisco powinno być znalezione i obsługiwane przez Area, a / SanFranciscoz - 404.

Oto jak szybko testuję trasy.

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

Problem polega na tym, że / SanFranciscoz jest zawsze obsługiwany przez stronę Area, ale chcę, aby 404. Ponadto, jeśli dodam NotFoundRoute do pierwszej konfiguracji trasy, wszystkie strony obszaru 404.

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

Co ja robię źle?

Oto sedno, które można pobrać i poeksperymentować.

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

4m1r
źródło
W przyszłości dla osób, które trafią na to pytanie, oprócz prawidłowej odpowiedzi poniżej, przeczytaj ten artykuł . Natknąłem się na to wcześniej i myślę, że ta osoba doskonale to wyjaśnia.
Dimitris Damilos

Odpowiedzi:

251

DefaultRoute i NotFoundRoute zostały usunięte wreak-router 1.0.0.

Chciałbym podkreślić, że domyślna trasa oznaczona gwiazdką musi być ostatnia na obecnym poziomie hierarchii, aby działała. W przeciwnym razie nadpisuje wszystkie inne trasy, które pojawiają się po niej w drzewie, ponieważ jest pierwsza i pasuje do każdej ścieżki.

Dla routerów React-Router 1, 2 i 3

Jeśli chcesz wyświetlić 404 i zachować ścieżkę ( taka sama funkcjonalność jak NotFoundRoute)

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

Jeśli chcesz wyświetlić stronę 404, ale zmienić adres URL ( taka sama funkcjonalność jak DefaultRoute)

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

Przykład z wieloma poziomami:

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

Do routerów React-Router 4 i 5

Trzymaj się ścieżki

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

Przekieruj na inną trasę (zmień adres URL)

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

Porządek ma znaczenie!

Janne Annala
źródło
jeśli masz aplikację redux, jak to zrobić: <Redirect from='*' to='/home' />w tej składni:const routes = { component: Main, childRoutes: [ { path: '/', component: Home }, ], indexRoute: { component: Main, }, };
tatsu
1
jeśli chcesz ustawić rekwizyty dla 404-Compontent, użyj tego kodu:<Route render={(props)=> <MyComponent myProp={someVar} {...props} />} />
Marco Weber
A co z 500 stronami? Podobnie jak strona, która ma się załadować, ale interfejs API wyświetla błąd. Jak to pokazać zamiast strony, która nie powiodła się przy zachowaniu trasy?
PixMach
<Redirect to = "/ 404" /> powoduje, że maksymalna głębokość aktualizacji przekracza w przypadku react-router-dom 5.0.0. Nawet jeśli strona 404 zostanie zamknięta, przekierowuje.
MiguelSlv
5
Nie lubię używać przekierowania, ponieważ ukrywa ono problematyczny adres URL przed użytkownikiem. Wymaga również dwukrotnego cofnięcia się, aby powrócić do poprzedniej strony.
sdgfsdh
39

W nowszych wersjach react-router chcesz zawijać trasy w Switch, który renderuje tylko pierwszy dopasowany komponent. W przeciwnym razie wyrenderowanych byłoby wiele komponentów.

Na przykład:

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
źródło
12
Nie musisz uwzględniać path="*"na trasie NotFound. Pominięcie pathspowoduje, że trasa będzie zawsze pasować.
chipit24
1
Dla osób spóźnionych @ chipit24 ma rację, aby uniknąć nieporozumień, po prostu pomiń pathcałkowicie nieznaną trasę
Altair312
14

W nowej wersji React Router (używającej teraz wersji 2.0.1) możesz użyć gwiazdki jako ścieżki do trasowania wszystkich „innych ścieżek”.

Więc wyglądałoby to tak:

<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
źródło
10

Ta odpowiedź dotyczy react-router-4. Możesz zawijać wszystkie trasy w bloku Switch, który działa tak samo jak wyrażenie przełącznika wielkości liter i renderuje składnik z pierwszą dopasowaną trasą. na przykład)

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

Kiedy użyć exact

Bez dokładnego:

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

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

Z dokładnym:

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

Teraz, jeśli akceptujesz parametry routingu i jeśli okaże się to nieprawidłowe, możesz sobie z tym poradzić w samym komponencie docelowym. na przykład)

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

Teraz w ProfilePage.js

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

Aby uzyskać więcej informacji, możesz przejść przez ten kod:

App.js

ProfilePage.js

Pransh Tiwari
źródło
6

Zgodnie z dokumentacją trasa została znaleziona, chociaż zasobu nie było.

Uwaga : to nie jest przeznaczone do użycia, gdy nie zostanie znaleziony zasób. Istnieje różnica między routerem, który nie może znaleźć pasującej ścieżki, a prawidłowym adresem URL, który powoduje, że nie można znaleźć zasobu. Adres URL kursów / 123 jest prawidłowym adresem URL i skutkuje dopasowaną trasą, dlatego został „znaleziony”, jeśli chodzi o routing. Następnie, jeśli pobieramy jakieś dane i odkryjemy, że kurs 123 nie istnieje, nie chcemy przechodzić na nową trasę. Podobnie jak na serwerze, podajesz adres URL, ale renderujesz inny interfejs użytkownika (i używasz innego kodu stanu). Nigdy nie powinieneś próbować przejść do NotFoundRoute.

Więc zawsze możesz dodać linię w Router.run()przed, React.render()aby sprawdzić, czy zasób jest prawidłowy. Po prostu prześlij rekwizyt do komponentu lub nadpisz Handlerkomponent niestandardowym, aby wyświetlić widok NotFound.

Brad B.
źródło
dzięki @brad, masz rację, musisz sobie z tym poradzić z komponentem i / lub zastąpić program obsługi przed router.run
4m1r
3
NotFound został wycofany github.com/reactjs/react-router/releases/tag/v1.0.0 , teraz użyj <Route path="*" to="/dest" />lub <Redirect from="*" to="/dest" />jako ostatniej pasującej trasy podrzędnej, jak sądzę
ptim
5

Właśnie rzuciłem okiem na twój przykład, ale jeśli dobrze go zrozumiałem, próbujesz dodać trasy 404 do dynamicznych segmentów. Kilka dni temu miałem ten sam problem, znalazłem # 458 i # 1103 i skończyło się na ręcznym sprawdzeniu w funkcji renderowania:

if (!place) return <NotFound />;

mam nadzieję, że to pomoże!

Jörn
źródło
dzięki @jorn, myślę, że masz rację, wydaje się, że można to rozwiązać tylko z poziomu komponentu
4m1r