【问题标题】:React-router TypeError: _this.props.history is undefinedReact-router TypeError:_this.props.history 未定义
【发布时间】:2017-08-08 23:55:51
【问题描述】:

我正在使用带有 react js 的 react-router,我按照他们的文档进行操作,但遇到了这个错误

编译时显示错误,

TypeError: _this.props.history is undefined

这是我的 index.js 文件

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';

ReactDOM.render(
  <Router history={browserHistory}>
    <Route path="/" component={App}>

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

这是我的 App.js 文件

import React, { Component } from 'react';
import './App.css';

class App extends Component {
    constructor(props){
        super(props);

        this.state = {
            headerText: "Props from Header.",
            contentText: "Props from content."
        };
    }
    render() {
        return (
          <div className="App">
            <ul>
                <li><a href="">Home</a></li>
                <li><a href="">Home</a></li>
                <li><a href="">Home</a></li>
            </ul>
          </div>
        );
    }
}

export default App;

【问题讨论】:

  • 你从哪里叫的?
  • 我在 index.js 文件中使用了路由器,您可以从代码中看到这一点。

标签: reactjs react-router


【解决方案1】:

这是因为 React Router 从 4.0.0 开始发生了变化。当您使用browserHistory 时,您现在应该使用来自react-router-dom 包的BrowserRouter。所以你的代码看起来像:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import { BrowserRouter, Route } from 'react-router-dom';

ReactDOM.render(
    <BrowserRouter>
        <Route path="/" component={ App }/>
    </BrowserRouter>, document.getElementById('root')
);

当然,你需要先安装react-router-dom

另请注意,如果您使用多个Route 元素,则必须使用Switch,如in this answer 所述。

【讨论】:

    【解决方案2】:

    对我来说,解决办法是改变

    1) 子组件

    <Route path="/path">
     <MyComponent/>
    </Route>
    

    2) 组件作为“组件”道具

    <Route path="/path" component={MyComponent}>
    </Route>
    

    它以两种方式呈现,所以对我来说非常困惑,在examples 他们提供的代码与第一个示例一样。 (我目前使用的是 5.1.2 版的“react-router-dom”包)。

    更新

    您也可以使用这种方式(对于子组件(“MyComponent”的子组件)仅适用于这个)

    import {withRouter} from 'react-router-dom';
    
    const componentClassWithHistory = withRouter(ChildComponent);
    export {componentClassWithHistory as ChildComponent};
    

    或默认导出

    export default withRouter(ChildComponent)
    

    或用于打字稿

    const componentClassWithHistory = (withRouter(ChildComponent as any) as any);
    export {componentClassWithHistory as ChildComponent};
    

    来源:https://reacttraining.com/react-router/core/api/withRouter

    希望对某人有所帮助。

    【讨论】:

    • 对于功能组件最好使用useHistory钩子;
    • 这里也一样,但我想将我的组件保留为子组件。您可以通过向每个组件添加 2 行来启用 withRouter 来做到这一点: 1) import { withRouter } from 'react-router-dom'; 2) 用Router(Home)导出默认值;这解决了我所有的问题。这个家伙博客的完整细节:dev.to/kozakrisz/…
    【解决方案3】:

    你在使用 npm 吗?我的 package.json 中的“react-router”:“^4.0.0”也有同样的问题。将其更改为 "react-router": "^3.0.2" 解决了我的问题。

    【讨论】:

    • "react-router": "^3.0.2" 对我有用。但不明白为什么 4.0.0 不起作用。
    • 我也是)我只是将它与我​​上次工作的 package.json 进行了比较。
    • 当你按照官方教程学习并且第 1 课不起作用时,这不是一个好兆头:>
    【解决方案4】:

    我的表单组件有问题。

    this.props.history.push('/') 未定义。

    为了解决这个问题,我添加了import {withRouter} from 'react-router-dom' 然后将默认组件导出为: export default withRouter(connect(mapStateToProps)(CustomForm));

    import React from "react";
    import { Form, Input, Button } from "antd";
    import { connect } from "react-redux";
    import {withRouter} from 'react-router-dom'
    import axios from "axios";
    
    const FormItem = Form.Item;
    
    
    class CustomForm extends React.Component {
    
      handleFormSubmit = async (event, requestType, articleID, ) => {
        event.preventDefault();
    
    const postObj = {
      title: event.target.elements.title.value,
      content: event.target.elements.content.value
    }
    
    axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
    axios.defaults.xsrfCookieName = "csrftoken";
    axios.defaults.headers = {
      "Content-Type": "application/json",
      Authorization: `Token ${this.props.token}`,
    };
    
    if (requestType === "post") {
      await axios.post("http://127.0.0.1:8000/api/create/", postObj)
        .then(res => {
          if (res.status === 201) {
            this.props.history.push(`/`);
          }
        })
    } else if (requestType === "put") {
      await axios.put(`http://127.0.0.1:8000/api/${articleID}/update/`, postObj)
        .then(res => {
          if (res.status === 200) {
            this.props.history.push(`/`);
          }
        })
    }
    
    
    };
    
      render() {
        return (
          <div>
            <Form
              onSubmit={event =>
                this.handleFormSubmit(
                  event,
                  this.props.requestType,
                  this.props.articleID
                )
              }
            >
              <FormItem label="Title">
                <Input name="title" placeholder="Put a title here" />
              </FormItem>
              <FormItem label="Content">
                <Input name="content" placeholder="Enter some content ..." />
              </FormItem>
              <FormItem>
                <Button type="primary" htmlType="submit">
                  {this.props.btnText}
                </Button>
              </FormItem>
            </Form>
          </div>
        );
      }
    }
    
    const mapStateToProps = state => {
      return {
        token: state.token
      };
    };
    
    export default withRouter(connect(mapStateToProps)(CustomForm));
    

    我希望这对某人有用。我使用 Django 作为后端

    【讨论】:

    • 谢谢,这正是我的菜鸟错误。
    【解决方案5】:

    您可以使用window.location.href = '/somePath' 作为最后的手段

    【讨论】:

    • 它正在工作,但此方法正在刷新我的页面。
    【解决方案6】:

    这对我有用>>>

    import { Router, Route, browserHistory, IndexRoute } from 'react-router';
    

    将 'react-router' 更改为 'react-router-dom',将 Router 更改为 BrowserRouter 作为路由器。

    像这样>>>

    import { BrowserRouter as Router, Route, browserHistory, IndexRoute } from 'react-router-dom';
    

    【讨论】:

      【解决方案7】:

      我试图在功能组件中使用history,但它未定义,因为我试图使用props 访问它。 根据文档,我们需要使用useHistory 挂钩来访问历史记录。这是根据文档的示例代码。

      import { useHistory } from "react-router-dom";
      function HomeButton() {
      
      
       let history = useHistory();
      
        function handleClick() {
          history.push("/home");
        }
      
        return (
          <button type="button" onClick={handleClick}>
            Go home
          </button>
        );
      }
      

      您可以查看此link 以获得更多了解。

      【讨论】:

        【解决方案8】:

        在我看来 this.props.history 没有定义,因为你没有将 routeProps 传递给你要渲染的组件。

        如下改变你的路线:

         <Route path="/home" render={(routeProps) => <Home {...routeProps}/>} />
        

        您还可以使用此方法将其他道具传递给渲染的组件。

        【讨论】:

        • 这只是在搜索了几个小时后为我省去了很多麻烦。非常感谢。
        • @Overcomer 乐于助人:)
        • 这实际上解决了 react-router 5.2 的问题。可能不是最好的方法,但由于我使用的是旧代码和升级框架,所以速度更快
        【解决方案9】:

        我在尝试实例化自己的路由器而不是使用内置路由器之一来处理an issue of having access to the history时遇到了这个问题:

        history.js

        import { createHashHistory as createHistory } from 'history'
        
        export default createHistory()
        

        root.jsx

        import { Router, Route } from 'react-router-dom'
        import history from './history'
        
        ...
        
          <Router history={history}>
            <Route path="/test" component={Test}/>
          </Router>
        

        就我而言,问题在于我将 history 包的一个版本锁定在 v2.1.2,而 react-router 在其自身的依赖项中依赖于 history 的 v4.x 版本。所以内置路由器使用较新的history 可以很好地实例化,但是当我自己尝试这样做时,我正在拉入较旧的history 并得到一个不兼容的对象。

        【讨论】:

          【解决方案10】:

          我有类似的东西:

          <Router>
             <HeaderComponent/>
             <Router exact path="/" component={Home}/>
             <Router path="/auth" component={AuthLayout}/>
             <FooterComponent/>
           </Router>
          

          AuthLayout 是一个组件,我在其中切换SignInSignUp 组件,如下所示:

          <div>
            { login ? <SignIn/> : <SignUp/> }
          </div>
          

          我在这些组件中遇到了this.props.history is not a function 的错误。这是因为我没有直接在路由器内部使用这些组件。我可以访问AuthLayout 中的this.props.history,我必须将它传递给它的孩子。

          所以我做到了:

          <div>
            { login ? <SignIn history={this.props.history}/> :  <SignUp history={this.props.history}/> }
          </div>
          

          问题解决了。

          【讨论】:

            【解决方案11】:

            以下解决方案适用于 ReactDOM.render

             <BrowserRouter>
              <Switch>
                <Route path="/home" component={Home} />
                <Route path="/user" component={User} />
                <Route path="*" component={page404} />
              </Switch>
             </BrowserRouter>
            

            它使用多个路由。

            【讨论】:

              【解决方案12】:

              这应该在被路由到的组件中完成。在这种情况下,它是 App 组件。因此,在 App.js 中,导入“createBrowserHistory”,如下所示:

              import React, { Component } from 'react';
              import './App.css';
              import { createBrowserHistory } from "history";
              
              class App extends Component {
                  constructor(props){
                      super(props);
              
                      this.history = createBrowserHistory();;
              
                      this.state = {
                          headerText: "Props from Header.",
                          contentText: "Props from content."
                      };
                  }
                  render() {
                      return (
                        <div className="App">
                          <ul>
                              <li><a href="">Home</a></li>
                              <li><a href="">Home</a></li>
                              <li><a href="">Home</a></li>
                          </ul>
                        </div>
                      );
                  }
              }
              
              export default App;
              

              【讨论】:

                【解决方案13】:

                检查是否有任何组件未链接到路由器或组件之间没有必要的链接。

                此外,如果您的一个可点击组件中有&lt;Router&gt;&lt;Link&gt;...&lt;/Link&gt;&lt;/Router&gt;,它可能会导致您的工作崩溃。

                希望对您有所帮助。

                【讨论】:

                  猜你喜欢
                  • 2016-07-31
                  • 1970-01-01
                  • 2015-09-08
                  • 2017-10-04
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-07-29
                  相关资源
                  最近更新 更多