React-Router:找不到路由?


130

考虑以下:

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

我有一个具有相同处理程序的App模板,HeaderTemplate和参数化路由集(在App模板内)。我希望能够在找不到某些内容时提供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始终由“区域”页面处理,但我希望将其处理到404。而且,如果我将NotFoundRoute添加到第一个路由配置,则所有“区域”页面404。

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

我究竟做错了什么?

这是一个要点,可以下载并进行试验。

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


除以下正确答案外,还有其他阅读本文的读者,以供将来遇到此问题的人员参考。我之前遇到过它,我认为那个人可以很好地解释它。
Dimitris Damilos

Answers:


245

在react-router 1.0.0中删除了DefaultRoute和NotFoundRoute。

我想强调一下,带有星号的默认路由必须在当前层次结构级别中处于最后位置才能起作用。否则,它将覆盖树中出现在其后的所有其他路由,因为它是第一个并匹配每个路径。

对于反应路由器1、2和3

如果要显示404并保留路径(与NotFoundRoute相同的功能)

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

如果要显示404页面但要更改网址(与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>

重定向到另一条路线(更改网址)

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

顺序很重要!


如果您有redux应用程序,您该怎么做:<Redirect from='*' to='/home' />用这种语法:const routes = { component: Main, childRoutes: [ { path: '/', component: Home }, ], indexRoute: { component: Main, }, };
tatsu

1
如果您想为404组件设置道具,请使用以下代码:<Route render={(props)=> <MyComponent myProp={someVar} {...props} />} />
Marco Weber

那500页呢?就像应该加载的页面一样,但API给出了错误。如何显示此内容而不是保留路线的失败页面?
PixMach

<重定向到=“ / 404” />导致最大更新深度超过react-router-dom 5.0.0。即使页面404退出,它也会重定向。
MiguelSlv '19

4
我不喜欢使用重定向,因为它向用户隐藏了有问题的URL。还需要回击两次才能返回上一页。
sdgfsdh

39

在较新版本的react-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')
);

12
您不需要包括path="*"在“未找到的路线”上。省略path将导致路线始终匹配。
chipit24 '17

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>

10

该答案适用于react-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之间存在差异。urlcourses / 123是有效的url,并导致匹配的路由,因此就路由而言,它是“找到的”。然后,如果我们获取一些数据并发现路线123不存在,则我们不想过渡到新路线。就像在服务器上一样,您可以继续提供网址,但是呈现不同的UI(并使用不同的状态代码)。您永远不要尝试过渡到NotFoundRoute。

因此,您总是可以在Router.run()之前添加一行React.render()以检查资源是否有效。只需将prop向下传递到组件,或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" />作为匹配的最后一个子路线,我相信
ptim

5

我只是快速浏览了您的示例,但是如果我理解正确,您将尝试向动态细分添加404路由。几天前,我遇到了同样的问题,发现了#458#1103并最终在render函数中进行了手工检查:

if (!place) return <NotFound />;

希望有帮助!


谢谢@jorn,我想你是对的,这似乎只能在组件级别解决
4m1r
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.