我正在关注Pluralsight的初学者教程,在表单上提交一个值传递给addUser
组件方法,我需要将userName推送到this.state.users
但是我收到错误
App.jsx:14 Uncaught TypeError: Cannot read property 'users' of undefined
组件
import React from 'react'
import User from 'user'
import Form from 'form'
class Component extends React.Component {
constructor() {
super()
this.state = {
users: null
}
}
// This is triggered on form submit in different component
addUser(userName) {
console.log(userName) // correctly gives String
console.log(this.state) // this is undefined
console.log(this.state.users) // this is the error
// and so this code doesn't work
/*this.setState({
users: this.state.users.concat(userName)
})*/
}
render() {
return (
<div>
<Form addUser={this.addUser}/>
</div>
)
}
}
export default Component
答案 0 :(得分:61)
当你调用{this.addUser}
时,它会被调用,这里this
是你的类(组件)的一个实例,因此它没有给你任何错误,因为addUser
方法确实存在你的班级scope
,
但当您使用addUser
方法时,您正在使用this
来更新存在于其中的state
类(组件)的范围,但目前你在addUser
方法的范围内,所以它给你一个错误,因为在addUser
范围内你没有像州,用户等。
因此,要处理此问题,您需要在调用this
方法时绑定addUser
。因此,您的方法始终知道this
的实例。
因此,代码中的最终更改将如下所示: -
<Form addUser={this.addUser.bind(this)}/>
或强>
<小时/> 您可以在构造函数中绑定this
,因为它应该是初始化的地方,因为当组件呈现给DOM
时,会首先调用构造函数方法。
所以你可以这样做: -
constructor(props) {
super(props);
this.state = {
users: null
}
this.addUser=this.addUser.bind(this);
}
现在您可以像以前一样以正常方式调用它: -
<Form addUser={this.addUser}/>
我希望这会奏效,我向你明确表示。
答案 1 :(得分:9)
@Vinit Raj的方法非常有效-我更喜欢使用箭头函数语法。
<Form addUser={ () => this.addUser() }/>
使用这样的匿名函数,您无需将其绑定到任何地方。
答案 2 :(得分:2)
如果您喜欢使用箭头功能,请执行此操作。箭头函数语法如下所示
addUser = event => {
const { value } = event.target;
console.log("value", value);
}
要防止在每次渲染或重新渲染时调用此函数,您需要
更改
<Form addUser={this.addUser}/>
收件人
<Form addUser={() => this.addUser()}/>
这样,仅当事件发生/触发时,才调用addUser
答案 3 :(得分:1)
在您的情况下,通过将函数声明为粗箭头函数,可以添加上下文并删除绑定到此的要求。它的工作原理与其他解决方案相同,但使编写和读取过程变得简单得多。只是改变...
addUser(userName) {
console.log(userName) // correctly gives String
console.log(this.state) // this is undefined
console.log(this.state.users) // this is the error
// and so this code doesn't work
/*this.setState({
users: this.state.users.concat(userName)
})*/
}
到...
addUser = (userName) => {
console.log(userName) // correctly gives String
console.log(this.state) // this is undefined
console.log(this.state.users) // this is the error
// and so this code doesn't work
/*this.setState({
users: this.state.users.concat(userName)
})*/
}
其他所有内容都可以保持不变。
答案 4 :(得分:0)
我遇到了同样的问题,但是我的问题是尝试在this.state = { ... }
调用完成之前访问this.state。正在执行类似this.state = { ...this.function1() }
和function1 = () => { a: this.state.b }
的操作。希望这对某人有帮助
答案 5 :(得分:0)
在函数中简单使用异步
addUser =async (userName) => {
console.log(this.state.users)
}
这会很好
答案 6 :(得分:0)
我认为其他答案不能很好地解释这一点。基本上,问题在于Javascript的this
关键字太疯狂了(MDN非常慷慨地说"behaves a little differently in JavaScript compared to other languages")。
TL; DR的意思是this
不一定是定义该方法的类。在this.addUser
元素中使用<Form>
时,this
实际上是Form
对象!我不确定为什么React会这样做-我真的不能认为为什么有人会想要这样做,但是很容易验证。只需将console.log(this)
放在addUser
中,您会发现它是Form
的实例。
无论如何,解决方案非常简单-使用箭头功能。箭头函数在定义它们的位置复制this
。因此,如果您像其他人所建议的那样在渲染函数中放入一个
<Form addUser={() => this.addUser()}/>
然后,当运行render()
时,this
将引用Component
对象,箭头函数将对其进行复制,然后在运行时将使用该副本。这基本上是该代码的简写(这是人们在使用箭头功能之前曾经做过的事情):
render() {
const that = this; // Make a copy of this.
return (
<div>
<Form addUser={function() { return that.addUser; }}/>
</div>
)
}
而且,正如其他人所提到的,每次调用渲染函数时创建一个新函数可能会影响性能,因此最好在其他地方捕获this
。我认为这是比其他人建议的更好的方法:
class Component extends React.Component {
constructor() {
super()
this.state = {
users: null
}
}
// This is triggered on form submit in different component
addUser = (userName) => {
this.setState({
users: this.state.users.concat(userName)
})
}
render() {
return (
<div>
<Form addUser={this.addUser}/>
</div>
)
}
}
但这是我使用React的第一天,我通常会尽量避免使用像Javascript一样完全吠叫的语言,因此请耐心等待所有这些!
答案 7 :(得分:0)
一个好的模式是将方法绑定到构造函数中的类。 看到 https://reactjs.org/docs/handling-events.html
import React from 'react'
import User from 'user'
import Form from 'form'
class Component extends React.Component {
constructor() {
super()
this.state = {
users: null
}
this.addUser = this.addUser.bind(this);
//bind functions which need access to "this"v in the constructor here.
}
// This is triggered on form submit in different component
addUser(userName) {
console.log(userName) // correctly gives String
console.log(this.state) // this is undefined
console.log(this.state.users) // this is the error
// and so this code doesn't work
/*this.setState({
users: this.state.users.concat(userName)
})*/
}
render() {
return (
<div>
<Form addUser={this.addUser}/>
</div>
)
}
}
export default Component
答案 8 :(得分:0)
问题就在这种情况下,所以使用
<form onSubmit={(event)=>this.addUser(event)}>
// Inputs
</form>
addUser(event){
event.preventDefault()
// Code this.state
}