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

react-router-dom v4 | Context Router and Route Undefined

我正在 运行ning 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 组件中添加一个 'Link' 组件时,它无法识别它。

//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: Cannot read property 'history' of undefined at Link.render (/Users/Ryan/Desktop/df/grnd/node_modules/react-router-dom/Link.js:76:35) at /Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:795:21 at measureLifeCyclePerf (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:75:12) at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:794:25) at ReactCompositeComponentWrapper._renderValidatedComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:821:32) at ReactCompositeComponentWrapper.performInitialMount (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:361:30) at ReactCompositeComponentWrapper.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:257:21) at Object.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactReconciler.js:45:35) at ReactDOMComponent.mountChildren (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactMultiChild.js:236:44) at ReactDOMComponent._createContentMarkup (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactDOMComponent.js:659:32)

如果我注释掉 App.js 中的 'Link' 组件,程序 运行 会从 index.js 加载 'App'。

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

我在这个例子中使用的历史是从给出的例子中提取的: https://reacttraining.com/react-router/web/api/Router/history-object

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

那么在v4中,Router只能有1个child。但在 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 中构建您的路由逻辑,这更有意义,因为您的 App 可能就是应用程序,因此它应该始终存在。

//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.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 >
    );

  }

}

当前代码

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

最近的错误

Warning: Failed context type: The context router is marked as required in Switch, but its value is undefined. in Switch (created by Main) in div (created by Main) in Main (created by App) in div (created by App) in App TypeError: Cannot read property 'route' of undefined at Switch.render (/Users/Ryan/Desktop/df/grnd/node_modules/react-router/Switch.js:48:36) at /Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:795:21 at measureLifeCyclePerf (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:75:12) at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:794:25) at ReactCompositeComponentWrapper._renderValidatedComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:821:32) at ReactCompositeComponentWrapper.performInitialMount (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:361:30) at ReactCompositeComponentWrapper.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactCompositeComponent.js:257:21) at Object.mountComponent (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactReconciler.js:45:35) at ReactDOMComponent.mountChildren (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactMultiChild.js:236:44) at ReactDOMComponent._createContentMarkup (/Users/Ryan/Desktop/df/grnd/node_modules/react-dom/lib/ReactDOMComponent.js:659:32)

我找出了导致错误的原因:服务器渲染

目前我正在使用这段代码

 //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(<App />) 并将其切换为类似 content: 'Hello' .... <Route/><Link/> 工作。