反应路由器dom v4 |上下文路由器和路由未定义

Posted

技术标签:

【中文标题】反应路由器dom v4 |上下文路由器和路由未定义【英文标题】:react-router-dom v4 | Context Router and Route Undefined 【发布时间】:2017-12-21 12:51:56 【问题描述】:

我正在运行 react-router-dom 4.1.1,我遵循了多个 React Router 指南,甚至做了在我的计算机上运行的 react-router-tutorial(尽管它使用的是 react-router v2 或类似的东西)。当我尝试在一个简单的应用程序上使用 react-router-dom v4 时,我遇到了很多错误。

向下滚动查看当前代码和错误

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import BrowserRouter as Router, Route, Switch from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory'

import App from './components/App';
import About from './components/pages/about';

const customHistory = createBrowserHistory()

ReactDOM.render((
  <Router history=customHistory>

    <Switch>
      <Route path='/' component=App />
      <Route path='/about' component=About/>
    </Switch>



  </Router>
), document.getElementById('root'))

此代码单独工作并呈现我的“应用”组件

但是当我尝试在我的 App 组件中添加一个“链接”组件时,它无法识别它。

//App.js
import React from 'react';
import Header from './Header';
import  Link  from 'react-router-dom'

class App extends React.Component 

  render() 
    return (
      <div className="App">

        <Header className="Header" header="Header" />


        <main className='main'>
            <Link to='about'>About</Link>
        </main>

      </div>
    );
  


export default App;

如果我运行它,我会收到错误:

TypeError:无法读取未定义的属性“历史” 在 Link.render (/Users/Ryan/Desktop/df/grnd/node_modules/react-router-dom/Link.js:76:35) 在 /Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:795:21 在 measureLifeCyclePerf (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:75:12) 在 ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:794:25) 在 ReactCompositeComponentWrapper._renderValidatedComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:821:32) 在 ReactCompositeComponentWrapper.performInitialMount (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:361:30) 在 ReactCompositeComponentWrapper.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:257:21) 在 Object.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactReconciler.js:45:35) 在 ReactDOMComponent.mountChildren (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactMultiChild.js:236:44) 在 ReactDOMComponent._createContentMarkup (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactDOMComponent.js:659:32)

如果我在 App.js 中注释掉“链接”组件,程序会运行并从 index.js 加载“应用程序”。

这只是我收到的许多错误中的一个,因为我试图弄清楚为什么我无法运行它。我还收到错误,其中显示“Route”未定义或“Router”不能嵌套子级等。我发现这个问题是最简单的。

我用于此示例的历史记录取自以下示例: https://reacttraining.com/react-router/web/api/Router/history-object

【问题讨论】:

【参考方案1】:

首先,你使用一个BrowserRouter,这个创建自己的历史对象并使用这个。因此,在您的情况下,您不应该将历史对象传递给它。实际上,在我查看 BrowserRouter 的代码后,它甚至应该在你的控制台中打印一个警告。如果我是你,我会把它命名为 BrowserRouter,这样在你阅读代码时它更不容易出错并且更清晰。

那么,在 v4 中,Router 只能有 1 个子节点。但在 Switch 的情况下,它实际上只挂载匹配的路由。我不确定它是否打算像这样,尝试将您的层次结构更改为不同的东西,并始终安装 Router 的子级。这是一个使用您的代码的示例:

//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import BrowserRouter, Route, Switch from 'react-router-dom';

import App from './components/App';

ReactDOM.render((
  <BrowserRouter>
    <App />    
  </BrowserRouter>
), document.getElementById('root'));

然后在您的应用程序中构建路由逻辑,这更有意义,因为您的应用程序可能就是应用程序,因此它应该始终存在。

//App.js
import React from 'react';
import Header from './Header';

class App extends React.Component 

  render() 

    return (
      <div className="App">
        <Header className="Header" header="Header" />
        <Switch>
          <Route exact path='/' component=Home />
          <Route path='/about' component=About/>
        </Switch>
      </div>
    );
  


我想你的链接可能在 Header 中,或者你可能想为此构建一个特殊的 Nav 组件,它可能包含在 Header 或其他地方。现在让我们在 Header 中执行它,看看它是如何工作的:

//Header.js
import React from 'react';
import Link from 'react-router-dom';

class Header extends React.Component 

  render() 

    return (
      <header className="header">
          <Link to='/'>Home</Link>
          <Link to='/about'>About</Link>
      </header >
    );

  


【讨论】:

在去掉历史对象并将 Switch 和 Route 组件放入 App 后,我收到此错误:警告:上下文类型失败:上下文 router 在 @ 中标记为必需987654325@,但其值为 undefinedTypeError: Cannot read property 'route' of undefined @ArnaudBoeglin 您仍然需要在您的应用周围安装路由器吗? 就像你的例子一样 开关在哪里?在层次结构中,它需要位于路由器之下。您可以从 package.json 粘贴您的依赖项吗?基本上你得到的错误说上面没有路由器来提供上下文.. 我的 Switch 组件在 App 中,就像您提供的示例一样。我的依赖是"dependencies": "ejs": "^2.5.6", "express": "^4.15.2", "mongodb": "^2.2.26", "node-sass-middleware": "^0.11.0", "react": "^15.5.4", "react-dom": "^15.5.4", "react-router": "^4.1.1", "react-router-dom": "^4.1.1" 【参考方案2】:

当前代码

//index.js

import React from 'react';
import ReactDOM from 'react-dom';
import  BrowserRouter  from 'react-router-dom';
import App from './components/App';

ReactDOM.render((
  <BrowserRouter>
    <App/>
  </BrowserRouter>
), document.getElementById('root'))

//App.js

import React from 'react';
import Header from './Header';
import Main from './Main';

class App extends React.Component 

  render() 
    return (
      <div className="App">

        <Header className="Header" header="Header" />

        <Main className="Main" />

      </div>
    );
  


export default App;

//Main.js

import React from 'react';
import  Switch, Route  from 'react-router-dom'
import Home from './Home';
import About from './About';

class Main extends React.Component 
    render() 
        return (
            <div className='Main-Container'>
                <Switch>
                    <Route exact path='/' component=Home />
                    <Route path='/about' component=About />
                </Switch>
            </div>
        )
    


export default Main;

最近的错误

警告:上下文类型失败:上下文router 被标记为 在Switch 中是必需的,但其值为undefined。 在 Switch 中(由 Main 创建) 在 div 中(由 Main 创建) 在 Main(由 App 创建) 在 div 中(由 App 创建) 在 App TypeError 中:无法读取未定义的属性“路由” 在 Switch.render (/Users/Ryan/Desktop/df/grnd/node_modules/react-router/Switch.js:48:36) 在 /Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:795:21 在 measureLifeCyclePerf (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:75:12) 在 ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:794:25) 在 ReactCompositeComponentWrapper._renderValidatedComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:821:32) 在 ReactCompositeComponentWrapper.performInitialMount (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:361:30) 在 ReactCompositeComponentWrapper.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:257:21) 在 Object.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactReconciler.js:45:35) 在 ReactDOMComponent.mountChildren (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactMultiChild.js:236:44) 在 ReactDOMComponent._createContentMarkup (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactDOMComponent.js:659:32)

【讨论】:

你能确认你已经安装了 prop-types 包吗?以防万一尝试安装它。没有它,上下文将无法按设计工作。【参考方案3】:

我发现了导致错误的原因:服务器渲染

目前,我正在使用这段代码

 //server.js

 server.get('/', (req, res) => 
      res.render('index', 
        content: ReactDOMServer.renderToString(<App />)
      );
    );

渲染到我的 ejs 模板

//index.ejs

<%- include('header') -%>
   <div id="root"><%- content -%></div>
<%- include('footer') -%>

当我注释掉 content: ReactDOMServer.renderToString(&lt;App /&gt;) 并将其切换为 content: 'Hello' .... &lt;Route/&gt;&lt;Link/&gt; 工作。

【讨论】:

以上是关于反应路由器dom v4 |上下文路由器和路由未定义的主要内容,如果未能解决你的问题,请参考以下文章

如何使用反应路由器 dom v4 配置 webpack 开发服务器?

如何将上下文 api 与反应路由器 v4 一起使用?

反应路由器 v4 默认页面(未找到页面)

使用 redux 保护的路由和身份验证反应路由器 v4

反应路由器:无法读取未定义的属性“路径名”

反应路由器 dom 推送