使用 React Router v4 的嵌套路由 - 解决方案

Posted

技术标签:

【中文标题】使用 React Router v4 的嵌套路由 - 解决方案【英文标题】:Nested Routes with React Router v4 - Solutions 【发布时间】:2017-08-23 04:19:34 【问题描述】:

我正在尝试让嵌套路由在 React Router v4 上运行。我指的是这个页面https://reacttraining.com/react-router/web/guides/quick-start

那么嵌套路由的做法是这样的

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>

    <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

这显然有效,但我想将其更改为类格式。

所以我在下面尝试了

index.js

render((
        <Router>
            <div>
                <Route path="/" component=App/>
            </div>
        </Router>
    ), document.getElementById('root')
);

App.js

class App extends Component 
    render() 
        return (
            <div className="container">
                <header>
                    <span className="icn-logo"><i className="material-icons">code</i></span>
                    <ul className="main-nav">
                        <li><Link to="/">Home</Link></li>
                        <li><Link to="/about">About</Link></li>
                        <li><Link to="/teachers">Teachers</Link></li>
                        <li><Link to="/courses">Courses</Link></li>
                    </ul>
                </header>
                <Route exact path="/" component=Home/>
                <Route path="/about" component=About/>
                <Route path="/teachers" component=Teachers/>
                <Route path="/courses" component=Course/>
            </div>
        );
    


export default App;

问题是,当我单击链接时,它会路由到正确的 url 并且它可以工作,但是当我自己输入 url 时,即使它们都呈现到相同的 url,它也会给出不能 GET /about 等等- 无论是我点击链接还是我自己输入它们。我在想App 路由除了在根目录下没有被渲染,我不明白为什么。有谁知道为什么会这样?

另外,我如何转换我的代码,以便我可以像第一个示例代码一样接受匹配参数?因此,在主题中,它将匹配对象作为参数,我猜这是对其先前 url 的某种引用

解决方案

好的,我将在这里提供解决方案,因为许多基于视频的 React Router 教程不包括 React Router v4。我希望在新的 React Router 上苦苦挣扎的菜鸟可以从这个答案中得到帮助。

所以基本上你必须能够区分客户端路由和资产请求,webpack-dev-server为此提供了一个完美的选择。

你所要做的就是添加

devServer: 
    port: 3000,
    historyApiFallback: 
        index:'index.html'
    

到 webpack.config.js,当服务器没有响应时,它总是指向 index.html

这是我的参考。阅读它可能有用https://jaketrent.com/post/pushstate-webpack-dev-server/

【问题讨论】:

【参考方案1】:

这通常是服务器问题,而不是客户端代码中的任何问题。如果您将 express 与静态服务一起使用:

app.use(express.static('build'));

然后,如果目录build 中没有文件,或者其他匹配的快速路由,例如/about 然后 express 不会回复任何内容。

除了上面的静态中间件之外,您还需要添加一个 catch all 路由来表达 - 但它必须在您的路由定义中。

app.get('*', (req, res) => 
    res.sendFile(path.join(__dirname, '../build', 'index.html'));
;

这是一个通配符路由,所以任何没有被静态中间件匹配的东西都会被发送到 index.html。一旦进入浏览器,react-router 就会接管并加载正确的组件。

【讨论】:

但那是节点......我正在使用 react 并使用 webpack 构建它。所以它应该仍然有效,不是吗?示例代码无需 express 即可工作 如果您收到错误Cannot GET /about,那么您正在运行的服务器正在寻找与/about 匹配的(服务器端)路由处理程序,但没有找到。这是您输入 URL 时的预期行为。 不,即使我使用服务器将所有内容路由到 index.html,它仍然无法正常工作。它的路径未定义。 请参考这里***.com/questions/31945763/… @DaurenAkilbekov 非常感谢。我花了一整天的时间试图解决这个问题,但你已经为我完成了!

以上是关于使用 React Router v4 的嵌套路由 - 解决方案的主要内容,如果未能解决你的问题,请参考以下文章

嵌套路由不使用React Router v4呈现

React Router v4 中的嵌套路由

浅入浅出 react-router v4 实现嵌套路由

React-router-dom v4 嵌套路由不起作用

如何在React Router v4中嵌套路由?

在 react-router v4 中嵌套路由