简体   繁体   English

在 React 中设置状态的正确方法是什么

[英]What is the correct way to set state in React

Honestly, this is my day 1 in ReactJS.老实说,这是我在 ReactJS 中的第一天。 I'm learning some small-small things like state .我正在学习一些小的东西,比如state I've created a small program for the toggle button.我为切换按钮创建了一个小程序。 It will simply display "Hello world!"它只会显示“Hello world!” or display nothing when the button is toggled.或在按钮切换时不显示任何内容。 There's one thing that I didn't understand.有一件事我不明白。 My code gives me an error when I use this syntax:当我使用此语法时,我的代码给了我一个错误:

  toggleHandler() {
    const currentStatus=this.state.display;
    this.setState({
      display: !currentStatus
    })
  }

this.state is undefined this.state 未定义

But the same code works perfectly If I change the syntax to a fat arrow function:但是如果我将语法更改为粗箭头函数,则相同的代码可以完美运行:

  toggleHandler=()=> {
    const currentStatus=this.state.display;
    this.setState({
      display: !currentStatus
    })
  }

I'll not waste your time.我不会浪费你的时间。 I've created an stackblitz .我创建了一个stackblitz Experts on the internet say that any call to this.setState() is asynchronous.互联网上的专家说,对this.setState()任何调用都是异步的。 So I tried using call back function and IIFE but got myself more confused and over-complicated.所以我尝试使用call back functionIIFE但让自己更加困惑和过于复杂。 Please correct me.请纠正我。 I'm sorry this is a very childish question.对不起,这是一个非常幼稚的问题。

There are a couple of ways.有几种方法。

One is to add in the constructor.一种是在构造函数中添加。 ES6 React.Component doesn't auto bind methods to itself . ES6 React.Component 不会自动绑定方法到它自己 You need to bind them yourself in constructor.您需要自己在构造函数中绑定它们。 Like this像这样

this.toggleHandler = this.toggleHandler.bind(this);

Another is arrow functions toggleHandler = (event) => {...}.另一个是箭头函数toggleHandler = (event) => {...}.

And then there is onClick={this.toggleHandler.bind(this)}然后是onClick={this.toggleHandler.bind(this)}

reference参考

Yes, any setState call is asynchronous.是的,任何 setState 调用都是异步的。 You can check your log that it changes his status but not manipulate the dom.你可以检查你的日志,它改变了他的状态,但不操纵 dom。 For manipulating the dom Any asynchronous call should be via a callback function.对于操作 dom 任何异步调用都应该通过回调函数。

you can bind any state with this arrow function or this.state.bind(this).您可以使用此箭头函数或 this.state.bind(this) 绑定任何状态。

What the error message is telling you is that the this object doesn't contain a property called state .错误消息告诉您的是this对象不包含名为state的属性。 What exactly this refers to is a constant source of confusion in JS, except when inside an arrow function.究竟this是指是混乱的在JS的恒定源,除了当一个箭头函数内部。 Inside an arrow function, this always refers to the context the arrow function appears in.在箭头函数内部, this总是指箭头函数出现的上下文。

The issue here is in the first example, this refers to the context sent to the handler by the onClick event.这里的问题是在第一个示例中, this是指由 onClick 事件发送到处理程序的上下文。 This context does not contain a state property.此上下文不包含state属性。 However, inside the arrow function, the this keyword will refer to the JavaScript class that your arrow function exists in. This class does have the state property.但是,在箭头函数内部, this关键字将引用您的箭头函数所在的 JavaScript 类。该类确实具有state属性。

To get around this, you can use bind (which outputs a copy of your function with the context set to whatever you supply it with. Or just use arrow functions. If it were me I would take the latter approach since this has better defined and more consistent behaviour inside an arrow function. If you do want to use bind , you would do this in your event handler declaration like so:为了解决这个问题,你可以使用bind (它输出你的函数的副本,上下文设置为你提供的任何内容。或者只是使用箭头函数。如果是我,我会采用后一种方法,因为this有更好的定义和箭头函数内更一致的行为。如果你想使用bind ,你可以在你的事件处理程序声明中这样做:

onClick={this.toggleHandler.bind(this)}

The way you can use functions and previous state.您可以使用函数的方式和以前的状态。

1- Binding in constructor 1- 在构造函数中绑定

constructor() {
    this.toggleHandler=this.toggleHandler.bind(this);
  }

can define like this可以这样定义

  toggleHandler=()=>{
    this.setState(prev=>({
      display: !prev.display
    }))
  }

2- arrow function (don't need to bind in constructor) 2-箭头函数(不需要在构造函数中绑定)

  toggleHandler=()=>{
    this.setState(prev=>({
      display: !prev.display
    }))
  }

3- Inline binding 3- 内联绑定

<Button onClick={this.toggleHandler.bind(this)}>Toggle</Button>

function code功能码

  toggleHandler=()=>{
    this.setState(prev=>({
      display: !prev.display
    }))
  }

4- Inline arrow function 4- 内联箭头函数

 <Button onClick={()=>this.toggleHandler()}>Toggle</Button>

function code功能码

  toggleHandler=()=>{
    this.setState(prev=>({
      display: !prev.display
    }))
  }

Note - Recommended to avoid inline functions for better performance注意 - 建议避免使用内联函数以获得更好的性能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM