React-router TypeError:_this.props.history未定义

时间:2017-03-17 12:13:53

标签: reactjs react-router

我正在使用react-router with react js和i遵循他们的文档但面临此错误

编译时

显示错误,

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;

13 个答案:

答案 0 :(得分:16)

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

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元素,则必须按in this answer解释使用Switch

答案 1 :(得分:9)

对我来说,解决方案是改变

1)作为子组件

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

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

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

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

更新

您也可以使用这种方式(对于子组件(“ 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

希望它对某人有帮助。

答案 2 :(得分:6)

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

答案 3 :(得分:6)

我的表单组件有问题。

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作为后端

答案 4 :(得分:2)

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

答案 5 :(得分:1)

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

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>


<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
   <left>
      <AnchorPane prefHeight="400.0" prefWidth="170.0" style="-fx-border-color: black; -fx-border-width: 0 2 0 0;" BorderPane.alignment="CENTER">
         <children>
            <ComboBox layoutY="2.0" prefHeight="25.0" prefWidth="170.0" />
            <RadioButton layoutY="27.0" mnemonicParsing="false" text="RadioButton" />
            <RadioButton layoutY="51.0" mnemonicParsing="false" text="RadioButton" />
            <RadioButton layoutY="74.0" mnemonicParsing="false" text="RadioButton" />
            <Label alignment="TOP_CENTER" layoutY="386.0" maxHeight="15.0" prefHeight="15.0" prefWidth="170.0" style="-fx-background-color: violet;" text="Label" AnchorPane.bottomAnchor="0.0" />
         </children>
      </AnchorPane>
   </left>
   <center>
      <AnchorPane prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
         <children>
            <TextField layoutY="2.0" prefHeight="165.0" prefWidth="330.0" promptText="WITAM" text="heh" AnchorPane.bottomAnchor="25.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
            <HBox layoutX="14.0" layoutY="147.0" prefHeight="25.0" prefWidth="320.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
               <children>
                  <Button maxWidth="1.7976931348623157E308" mnemonicParsing="false" prefHeight="25.0" text="Button" />
                  <Button mnemonicParsing="false" text="Button" />
               </children>
            </HBox>
         </children>
      </AnchorPane>
   </center>
</BorderPane>

它使用多个路由。

答案 6 :(得分:1)

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

如下更改路线:

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

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

答案 7 :(得分:1)

这对我有用>>>

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

将“react-router”更改为“react-router-dom”,将路由器更改为 BrowserRouter 作为路由器。

像这样>>>

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

答案 8 :(得分:1)

我试图在函数组件中使用 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 以获得更多理解。

答案 9 :(得分:0)

在尝试实例化自己的路由器而不是使用内置路由器之一来处理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 :(得分:0)

这应该在要路由到的组件中完成。在这种情况下,它是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;

答案 11 :(得分:0)

我有类似的东西:

<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的错误。这是因为我没有直接在路由器内部使用这些组件。我可以访问this.props.history内部的AuthLayout,并且必须将其传递给它的子级。

所以我做到了:

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

问题解决了。

答案 12 :(得分:0)

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

除了您的可点击组件之一中有<Router><Link>...</Link></Router>之外,它还可能使您的工作崩溃。

希望这会有所帮助。