我是ReactJS的新手,但我想创建一个具有登录和注销功能的简单域。我将用户凭据存储在AsyncStorage中。这是我的index.js:
..
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
..
class Index extends Component {
render() {
return (
<Router>
<Switch>
<Route path='/' exact component={Home}/>
<Route path='/login' component={Login}/>
<Route path='/welcome' component={Welcome}/>
</Switch>
</Router>
);
}
}
ReactDOM.render(<Index />, document.getElementById('root')); registerServiceWorker();
在首页页面上,有一个按钮可以移至登录页面:
<Button color="primary" onClick={() => {this.props.history.push("/login")}}>Sign In</Button>
登录组件包含表单,该表单在提交给定方法时调用:
this.props.history.push("/welcome");
最后,在欢迎页面上,我按下了按钮:
class Welcome extends Component {
handleLogout() {
this.props.history.push("/");
}
render() {
return (
<div>
<h1>Hello!</h1>
<Button onClick={this.handleLogout}>Logout</Button>
</div>
);
}
}
export default withRouter(Welcome);
我想说的是,每个组件(首页,登录,欢迎)都与Routerr组件一起包装,但是一旦单击欢迎页面上的按钮,发生错误:
TypeError:无法读取未定义的属性“历史”
任何帮助将不胜感激:)
答案 0 :(得分:2)
在javascript中,this
的值直到实际调用函数才确定。而且由于onClick是异步发生的,因此handleLogout将在没有上下文的情况下被调用,这意味着this
在非严格模式下绑定到窗口对象,或者在严格模式下未定义。您显然处于非严格模式,因此this.props.history.push
与window.props.history.push
相同。 window.props
未定义,导致错误。
有几种方法可以解决此问题:
1)在渲染中使用箭头功能。箭头函数与声明时具有相同的值this
,因此this
将等于您的组件
<Button onClick={(event) => this.handleLogout(event)}/>
2)在构造函数中明确绑定handleLogout函数。这将创建一个新函数,该函数的this
的值已锁定。
class Welcome extends Component {
constructor(props) {
super(props);
this.handleLogout = this.handleLogout.bind(this);
}
handleLogout() {
this.props.history.push("/");
}
//etc
}
3)如果您使用的是babel-plugin-transform-class-properties插件,请将handleLogout定义为箭头函数:
class Welcome extends Component {
handleLogout = () => {
this.props.history.push("/");
}
//etc
}
答案 1 :(得分:2)
这与this
的定义方式有关。您是在组件的上下文中定义handleLogout
,然后将其传递到另一个上下文中并在其中执行。 this
在那种情况下会有所不同,因此为何未定义道具。
基本上,如果要将函数传递到其他上下文中(并且您需要从this
访问某些内容(例如props或state),则需要将该函数绑定到this
的组件版本。可以通过两种常见方式之一来做到这一点
在组件的构造函数中:
constructor(props) {
super(props)
this.handleLogout = this.handleLogout.bind(this);
}
或通过使用箭头功能(此“自动绑定”)定义您的方法-但此方法尚未完全批准,因此很可能需要babel polyfill:
handleLogout = () => { // function code }
答案 2 :(得分:1)
这是人们在反应中遇到的一个非常普遍的问题,您没有将适当的范围传递给处理程序函数。因此,在调用handleLogout时,作用域(用'this'表示)不包含道具。您需要先将“ this”绑定到该处理函数,然后再传递给子组件。您可以通过在将按钮提供给Button时使用箭头功能来实现此目的(箭头功能会自动将范围向下传递):
<Button
onClick={() => this.handleLogout()}
>
Logout
</Button>
或者您可以将其绑定到构造函数中的处理函数:
class Welcome extends Component {
constructor(props) {
super(props);
this.handleLogout = this.handleLogout.bind(this);
}
每当您在React中看到指示未定义道具的错误时,“ this”应该是您检查的第一件事。 (双关语意!)
答案 3 :(得分:0)