为什么我不能在React-Router 4.x中嵌套Route组件?

11

如何在react-router中使用嵌套路由,特别是在4.x版本中?以下内容在以前的版本中效果很好...

<Route path='/stuff' component={Stuff}>
  <Route path='/stuff/a' component={StuffA} />
</Route>

升级到4.x版本后会出现以下警告...

警告:不应该在同一路由中同时使用<Route>组件和<Route children>;<Route children>将被忽略

这是怎么回事?我已经在文档中搜索了几个小时,但无法成功地使嵌套路由工作。在react-router v4中如何使用<Route>组件来嵌套路由?我的简单示例如何转换为v4.x API兼容的方式来嵌套路由?


这个文档中的示例难道不是你要找的吗?特别是RouteWithSubRoutes - paqash
1
可能是 Nested routes with react router v4 的重复问题。 - paqash
2个回答

11

忘记你所知道的React Router版本< v4。你通过嵌套<Routes>来嵌套路由。请查看此示例。特别是查看Topics组件。你不会预先声明你的路由,而是在组件渲染时动态声明。

import React from 'react'
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'

const BasicExample = () => (
  <Router>
    <div>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
        <li><Link to="/topics">Topics</Link></li>
      </ul>

      <hr/>

      <Route exact path="/" component={Home}/>
      <Route path="/about" component={About}/>
      <Route path="/topics" component={Topics}/>
    </div>
  </Router>
)

const Home = () => (
  <div>
    <h2>Home</h2>
  </div>
)

const About = () => (
  <div>
    <h2>About</h2>
  </div>
)

const Topics = ({ match }) => (
  <div>
    <h2>Topics</h2>
    <ul>
      <li>
        <Link to={`${match.url}/rendering`}>
          Rendering with React
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/components`}>
          Components
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/props-v-state`}>
          Props v. State
        </Link>
      </li>
    </ul>

    {/* NESTED ROUTES */}
    <Route path={`${match.url}/:topicId`} component={Topic}/>
    <Route exact path={match.url} render={() => (
      <h3>Please select a topic.</h3>
    )}/>
  </div>
)

const Topic = ({ match }) => (
  <div>
    <h3>{match.params.topicId}</h3>
  </div>
)

export default BasicExample

1
别担心。给V4一个机会。一开始可能会感觉有点奇怪,但是API被改成这样有很好的理由。它更加强大,而且只是“组件”。 - Tyler McGinnis
@scniro 感谢您指出router5,我现在正在研究它。React-router甚至搞乱了我们所拥有的面包屑和其他依赖项。 - Shawn Mclean
@TylerMcGinnis,是否可以嵌套路由,例如path={`${match.url}/:topicId/edit`},它将显示一个新页面,您可以在其中编辑主题,并且不会继承来自“TopicId”的布局? - Dimo
react-router v4 真的很糟糕。它还将你的测试与路由器耦合在一起。因此,即使你测试的行为与自定义路由无关,你的测试也被迫知道 react-router 作为一个依赖项,并且你必须使用 MemoryRouter 包装你的测试,这真的很糟糕。这样会导致测试泄漏,你的测试变得更不隔离并且与这个垃圾耦合。 - PositiveGuy
那个例子不好,让我更新一下。我有另一个没有那个检查的,设置相同但仍然有效。 - PositiveGuy
显示剩余2条评论

1
使用react-router v4和v5,您还可以使用`render` prop来嵌套路由。
<Route 
  path='/stuff' 
  render={({ match: { url } }) => (
    <>
      <Route path={`${url}/`} component={Stuff} exact />
      <Route path={`${url}/a`} component={StuffA} />
    </>
  )} 
/>

在我看来,与将子路由拆分为通过component属性传递的单独定义的组件相比,在大多数情况下,这种语法更易读。
我在类似问题的答案中发布了一个帖子,但注意到这个问题也有很多浏览量,所以认为将其移植到这里会很有帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接