反应this.state未定义?

Iva*_*pić 38 reactjs

我正在关注Pluralsight的初学者教程,在表单上提交一个值传递给addUser组件方法,我需要将userName推送到this.state.users但是我得到错误

 App.jsx:14 Uncaught TypeError: Cannot read property 'users' of undefined
Run Code Online (Sandbox Code Playgroud)

零件

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
Run Code Online (Sandbox Code Playgroud)

Vin*_*Raj 76

当你调用{this.addUser}它时,它会被调用,这里this是你的类(组件)的一个实例,因此它不会给你带来任何错误,因为addUser你的类中存在方法scope,但是当你在addUser方法下时,你this用来更新state存在于类(组件)的范围,但目前你在addUser方法的范围内,所以它给你一个错误,因为在addUser你没有像状态,用户等任何东西.所以要处理这个问题你需要绑定,this而你在调用addUser因此,您的方法始终知道实例this.

因此,代码的最终更改将如下所示: -

<Form addUser={this.addUser.bind(this)}/>
Run Code Online (Sandbox Code Playgroud)

要么


您可以this在构造函数中进行绑定,因为它是您应该初始化事物的地方,因为构造函数方法在组件呈现时首先被调用DOM.

所以你可以这样做: -

  constructor(props) {
    super(props);
    this.state = {
        users: null
    }
    this.addUser=this.addUser.bind(this);
}
Run Code Online (Sandbox Code Playgroud)

现在您可以像以前一样以正常方式调用它: -

<Form addUser={this.addUser}/>
Run Code Online (Sandbox Code Playgroud)

我希望这会奏效,我向你明确表示.

  • 为什么构造函数和渲染函数正确理解'this',但是addUser却未定义它? (3认同)
  • @Loreno,函数是对象,并且具有自身的作用域。使用bind(this)或函数表达式(lambda表达式),我们将函数的范围定义为当前类。我希望这会有所帮助。 (2认同)

Fil*_*org 10

@Vinit Raj的方法非常有效 - 我更喜欢使用箭头函数语法.

<Form addUser={ () => this.addUser() }/>
Run Code Online (Sandbox Code Playgroud)

使用这样的匿名函数,您无需将其绑定到任何位置.

  • 这将在每个具有性能影响的渲染上创建一个新功能。由于该函数不接受任何参数,因此最好这样声明:`&lt;Form addUser = {this.addUser} /&gt;`并使用诸如addUser =()=&gt;这样的箭头函数声明add user。 ..` (3认同)
  • 整个“这可能会导致性能问题”的比喻是死马。对其进行基准测试以证明它,而不是传播技术废话。如何证明在“this”上调用“bind”比创建新的箭头函数更快?事实是,它可能非常小,以至于在基准测试中几乎无法检测到。两者之间任何可能的偏差都被网络延迟等因素的不确定性所抵消。使用更具可读性的那个,直到*它实际上成为代码中可测量的瓶颈*。 (2认同)

Hem*_*ari 5

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

addUser = event => { 
    const { value }  = event.target;
    console.log("value", value);
}
Run Code Online (Sandbox Code Playgroud)

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

改变

<Form addUser={this.addUser}/>
Run Code Online (Sandbox Code Playgroud)

<Form addUser={() => this.addUser()}/>
Run Code Online (Sandbox Code Playgroud)

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

  • 除非您像“&lt;Form addUser={this.addUser()}/&gt;”这样内联调用,否则不会在每次渲染时调用它 (2认同)