React-router TypeError:_this.props.history 未定义
Posted
技术标签:
【中文标题】React-router TypeError:_this.props.history 未定义【英文标题】:React-router TypeError: _this.props.history is undefined 【发布时间】: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 文件中使用了路由器,您可以从代码中看到这一点。 【参考方案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
是一个组件,我在其中切换SignIn
和SignUp
组件,如下所示:
<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】:检查是否有任何组件未链接到路由器或组件之间没有必要的链接。
此外,如果您的一个可点击组件中有<Router><Link>...</Link></Router>
,它可能会导致您的工作崩溃。
希望对您有所帮助。
【讨论】:
以上是关于React-router TypeError:_this.props.history 未定义的主要内容,如果未能解决你的问题,请参考以下文章
TypeError:使用来自 react-router 的 useParams 时无法读取未定义的属性“匹配”
渲染中的错误:“TypeError:无法读取未定义的属性'_t'”在使用 Jest 的单元测试中
如何使用 react-router 通过 Route 渲染传递 redux 商店道具?
错误:TimeoutException Future 未完成并且 TypeError:T.as 不是 _Future.new 的函数。[_setValue]