React-Router: не найден маршрут?

132

Обратите внимание на следующее:

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

У меня есть шаблон приложения, шаблон HeaderTemplate и параметризованный набор маршрутов с одним и тем же обработчиком (в шаблоне приложения). Я хочу иметь возможность обслуживать 404 маршрута, когда что-то не найдено. Например, / CA / SanFrancisco должен быть найден и обработан Area, тогда как / SanFranciscoz должен быть 404.

Вот как я быстро тестирую маршруты.

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

Проблема в том, что / SanFranciscoz всегда обрабатывается страницей Area, но я хочу, чтобы это было 404. Кроме того, если я добавлю NotFoundRoute к первой конфигурации маршрута, все страницы Area 404.

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

Что я делаю не так?

Вот суть, которую можно скачать и поэкспериментировать.

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

4m1r
источник
Для будущих справок для людей, которые задаются этим вопросом, кроме правильного ответа ниже, прочтите эту статью . Я столкнулся с этим раньше, и я думаю, что этот человек прекрасно это объясняет.
Димитрис Дамилос

Ответы:

251

DefaultRoute и NotFoundRoute были удалены в react-router 1.0.0.

Я хотел бы подчеркнуть, что для работы маршрут по умолчанию со звездочкой должен быть последним на текущем уровне иерархии. В противном случае он переопределит все другие маршруты, которые появляются после него в дереве, потому что он первый и соответствует каждому пути.

Для реактивного маршрутизатора 1, 2 и 3

Если вы хотите отобразить 404 и сохранить путь (те же функции, что и NotFoundRoute)

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

Если вы хотите отобразить страницу 404, но изменить URL-адрес (те же функции, что и DefaultRoute)

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

Пример с несколькими уровнями:

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

Для реактивных маршрутизаторов 4 и 5

Держи путь

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

Перенаправить на другой маршрут (сменить URL)

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

Порядок имеет значение!

Янне Аннала
источник
если у вас есть приложение Redux как вы: <Redirect from='*' to='/home' />в этом syntaxe:const routes = { component: Main, childRoutes: [ { path: '/', component: Home }, ], indexRoute: { component: Main, }, };
Tatsu
1
если вы хотите установить реквизиты для 404-компонента, используйте этот код:<Route render={(props)=> <MyComponent myProp={someVar} {...props} />} />
Марко Вебер,
А как насчет 500 страниц? Как страница, которая должна загружаться, но API выдает ошибку. Как это показать вместо страницы, на которой произошел сбой при сохранении маршрута?
PixMach
<Redirect to = "/ 404" /> вызывает превышение максимальной глубины обновления на response-router-dom 5.0.0. Даже если страница 404 закрывается, выполняется перенаправление.
MiguelSlv
5
Мне не нравится использовать перенаправление, потому что оно скрывает проблемный URL от пользователя. Для возврата на предыдущую страницу также требуется дважды вернуться.
sdgfsdh
39

В более новых версиях response-router вы хотите обернуть маршруты в Switch, который отображает только первый совпавший компонент. В противном случае вы увидите несколько визуализированных компонентов.

Например:

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
источник
12
Вам не нужно включать path="*"в NotFound Route. Если пропустить path, маршрут всегда будет совпадать.
chipit24
1
Для тех, кто приходит поздно, @ chipit24 подходит, чтобы избежать путаницы, просто опустите pathполностью для неизвестных маршрутов
Altair312
14

В новой версии React Router (сейчас используется 2.0.1) вы можете использовать звездочку в качестве пути для маршрутизации всех «других путей».

Так это выглядело бы так:

<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
источник
10

Это ответ для response-router-4. Вы можете обернуть все маршруты в блок Switch, который работает так же, как выражение switch-case, и отображает компонент с первым совпадающим маршрутом. например)

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

Когда использовать exact

Без точного:

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

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

С точным:

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

Теперь, если вы принимаете параметры маршрутизации, и если они оказываются неверными, вы можете обработать их в самом целевом компоненте. например)

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

Теперь в ProfilePage.js

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

Для получения дополнительной информации вы можете пройти через этот код:

App.js

ProfilePage.js

Пранш Тивари
источник
6

Согласно документации , маршрут был найден, хотя ресурса нет.

Примечание : это не предназначено для использования, когда ресурс не найден. Существует разница между маршрутизатором, не находящим совпадающий путь, и действительным URL-адресом, в результате которого ресурс не найден. URL-адрес course / 123 является допустимым URL-адресом и приводит к совпадению маршрута, поэтому он был "найден" в отношении маршрутизации. Затем, если мы извлекаем некоторые данные и обнаруживаем, что курс 123 не существует, мы не хотим переходить на новый маршрут. Как и на сервере, вы отправляете URL-адрес, но визуализируете другой пользовательский интерфейс (и используете другой код состояния). Вы никогда не должны пытаться перейти на NotFoundRoute.

Итак, вы всегда можете добавить строку Router.run()перед, React.render()чтобы проверить, действителен ли ресурс. Просто передайте опору компоненту или замените Handlerкомпонент пользовательским, чтобы отобразить представление NotFound.

Брэд Б.
источник
спасибо @brad, вы правы, вы должны справиться с этим с помощью компонента и / или переопределить обработчик до router.run
4m1r
3
NotFound устарел github.com/reactjs/react-router/releases/tag/v1.0.0 , теперь используйте <Route path="*" to="/dest" />или <Redirect from="*" to="/dest" />в качестве последнего
подмаршрута
5

Я только что взглянул на ваш пример, но если я правильно понял, вы пытаетесь добавить 404 маршрута к динамическим сегментам. У меня была такая же проблема пару дней назад, я нашел # 458 и # 1103 и закончил с ручной проверкой в ​​функции рендеринга:

if (!place) return <NotFound />;

надеюсь, это поможет!

Йорн
источник
спасибо @jorn, я думаю, что вы правы, кажется, что это возможно только на уровне компонентов
4m1r