【问题标题】:React-Router: No Not Found Route?React-Router:没有找不到路由?
【发布时间】:2025-12-16 11:00:02
【问题描述】:

考虑以下几点:

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 始终由区域页面处理,但我希望它为 404。此外,如果我将 NotFoundRoute 添加到第一个路由配置,则所有区域页面都是 404。

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

我做错了什么?

这是一个可以下载和试验的要点。

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

【问题讨论】:

  • 供最终解决此问题的人将来参考,除了下面的正确答案,请阅读this article。我之前遇到过,我认为那个人解释得很好。

标签: javascript reactjs react-router


【解决方案1】:

DefaultRoute 和 NotFoundRoute 在 react-router 1.0.0 中被移除。

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

对于 react-router 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>

对于 react-router 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 应用程序你会怎么做:&lt;Redirect from='*' to='/home' /&gt; 在这个语法中:const routes = { component: Main, childRoutes: [ { path: '/', component: Home }, ], indexRoute: { component: Main, }, };
  • 如果你想为 404 组件设置 props,请使用此代码:&lt;Route render={(props)=&gt; &lt;MyComponent myProp={someVar} {...props} /&gt;} /&gt;
  • 500 页怎么样?就像一个应该加载但 API 给出错误的页面。如何在保持路线的同时显示这个而不是失败的页面?
  • 我不喜欢使用重定向,因为它对用户隐藏了有问题的 URL。它还需要返回两次才能返回上一页。
  • @PixMach 您可以在错误处理程序reactrouter.com/web/api/history 中使用 history.push(/500),或者让它抛出并利用 React 错误边界以获得更全局的选项:reactjs.org/docs/error-boundaries.html
【解决方案2】:

在较新版本的 react-router 中,您希望 wrap the routes in a 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')
);

【讨论】:

  • 您不需要在 NotFound 路由中包含 path="*"。省略 path 将导致 Route 始终匹配。
  • 对于迟到的人,@chipit24 是正确的,为了避免混淆,请完全省略未知路线的 path
【解决方案3】:

使用新版本的 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>

【讨论】:

    【解决方案4】:

    此答案适用于 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

    【讨论】:

      【解决方案5】:

      根据documentation,找到了路径,即使资源没有找到。

      注意:这不适用于找不到资源的情况。路由器找不到匹配的路径与导致找不到资源的有效 URL 之间存在差异。 url course/123 是一个有效的 url 并导致匹配的路由,因此就路由而言,它是“找到的”。然后,如果我们获取一些数据并发现路线 123 不存在,我们不想转换到新路线。就像在服务器上一样,您继续提供 url,但呈现不同的 UI(并使用不同的状态代码)。您永远不应该尝试过渡到 NotFoundRoute。

      因此,您始终可以在Router.run() 中的React.render() 之前添加一行以检查资源是否有效。只需将 prop 向下传递给组件或使用自定义组件覆盖 Handler 组件即可显示 NotFound 视图。

      【讨论】:

      • 感谢@brad,你是对的,你必须用组件处理这个问题,或者在 router.run 之前覆盖处理程序
      • NotFound 已弃用 github.com/reactjs/react-router/releases/tag/v1.0.0,现在使用 &lt;Route path="*" to="/dest" /&gt;&lt;Redirect from="*" to="/dest" /&gt; 作为匹配的最后一个子路由,我相信
      【解决方案6】:

      对于使用 react router v6 的用户

      Redirect 组件已从 react-router 版本 6 中删除。 对于react-router-dom v6,只需将Redirect 替换为Navigate

      Migrating up to v6

      npm install react-router-dom@6

      import {Routes, Route, Navigate } from "react-router-dom";
      
      function App() {
          return (
              <div>
                  <Routes>
                      <Route path="/404" element={<div>Choose the correct path/div>} />
                      <Route path="*" element={<Navigate replace to="/404" />} />
                  </Routes>
              </div>
          );
      }
      

      【讨论】:

        【解决方案7】:

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

        if (!place) return <NotFound />;
        

        希望有帮助!

        【讨论】:

        • 感谢@jorn,我认为你是对的,这似乎只能从组件级别解决
        • @Jorn - 所以你说的 uri 是我们需要使用一些脚本在本地验证然后返回 &lt;NotFound&gt; 。对吗?
        【解决方案8】:

        上面的答案是正确的,对于之前的反应 5。在 React v6 中,Switch 不再存在。此解决方案适用于 react v6

        import {BrowserRouter as Router, Routes, Route, Link} from "react-router-dom";
        
        ...
        
        <Router>
            <ul>
                <li>
                    <Link to="t1">component1</Link>
                </li>
                <li>
                    <Link to="t2">component2</Link>
                </li>
            </ul>
        
            <Routes>
                <Route path="/t1" exact element={<Component1/>}/>
                <Route path="/t2" exact element={<Component2/>}/>
                <Route path="*" element={<NotFound/>}/>
            </Routes>
        
        </Router>
        

        【讨论】:

          【解决方案9】:

          React 路由器 v6

          现场演示:Redirect Default or 404 Routes with React Router

          示例代码:

          <Router>
            <Routes>
              <Route path="users" element={<Users />} />
              <Route path="posts" element={<Posts />} />
            </Routes>
          </Router>
          

          要重定向并导航到我们选择的路由之一,我们可以使用来自 React Router 的 &lt;Navigate&gt; 组件。现在我们可以在路由配置下面声明空路由的情况,如下所示:

          <Router>
            <Routes>
              <Route path="users" element={<Users />} />
              <Route path="posts" element={<Posts />} />
              <Route path="" element={<Navigate to="/users" />} />
            </Routes>
          </Router>
          

          【讨论】: