react this.state 是未定义的?

IT技术 reactjs
2021-04-19 04:18:34

我正在关注 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
6个回答

当你调用时{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}/>

我希望这会奏效,我向你说清楚了。

@Loreno,函数是对象并且有自己的作用域。使用 bind(this) 或函数表达式(lambda 表达式),我们将函数的作用域定义为当前类。我希望这会有所帮助。
2021-05-27 04:18:34
为什么构造函数和渲染函数正确理解“this”,但 addUser 将其设为未定义?
2021-06-21 04:18:34
@Loreno Component(包含其他 HTML 元素的已定义组件)调用contstructorrender,但Form组件内的元素试图调用addUser,但是,它不包含对该函数的引用。其他人建议使用代码,{ () => this.addUser() }因为这段代码addUserrender函数范围内调用,意思this是指Component而不是Form
2021-06-21 04:18:34

@Vinit Raj 的方法非常有效——不过我更喜欢像这样使用箭头函数语法。

<Form addUser={ () => this.addUser() }/>

使用像这样的匿名函数,你不需要在任何地方绑定它。

整个“这可能会导致性能问题”的比喻是一匹死马。对其进行基准测试以证明它,而不是传播技术胡言乱语。你怎么能证明调用bindthis比创建一个新的箭头功能更快?事实是,它可能太小以至于无法在基准测试中检测到。网络延迟等因素的不确定性大大超过了两者之间任何可能的偏差。使用更易读的那个,直到它真正成为你代码中的一个可衡量的瓶颈
2021-05-31 04:18:34
这将在每个渲染上创建一个具有性能影响的新函数。由于该函数不接受任何参数,因此最好像这样声明它:<Form addUser={ this.addUser }/>并使用箭头函数声明添加用户,例如addUser = () => ...
2021-06-03 04:18:34

如果您更喜欢使用箭头函数,请执行此操作。箭头函数语法如下

addUser = event => { 
    const { value }  = event.target;
    console.log("value", value);
}

为了防止在每次渲染或重新渲染时调用此函数,您需要

改变

<Form addUser={this.addUser}/>

<Form addUser={() => this.addUser()}/>

这样 addUser 只会在事件发生/触发时被调用

除非您将调用内联,否则不会在每次渲染时调用它 <Form addUser={this.addUser()}/>
2021-06-20 04:18:34

我遇到了同样的问题,但我的问题是在this.state = { ... }呼叫完成之前尝试访问 this.state 正在做这样的事情this.state = { ...this.function1() }function1 = () => { a: this.state.b }希望这有助于某人

在您的情况下,通过将您的函数声明为胖箭头函数,您可以添加上下文并删除绑定到 this 的要求。这与其他解决方案的工作原理相同,但使写入和读取都变得更加简单。只是改变...

 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)
    })*/
}

其他一切都可以保持不变。