简体   繁体   English

防止this.state与setState一起使用

[英]Prevent this.state to be used with setState

The reference states: 参考说明:

setState() does not always immediately update the component. setState()并不总是立即更新组件。 It may batch or defer the update until later. 它可以批量推迟更新或推迟更新。 This makes reading this.state right after calling setState() a potential pitfall. 这使得在调用setState()之后立即读取this.state是一个潜在的陷阱。 Instead, use componentDidUpdate or a setState callback (setState(updater, callback)), either of which are guaranteed to fire after the update has been applied. 相反,使用componentDidUpdate或setState回调(setState(更新程序,回调)),其中任何一个都保证在应用更新后触发。 If you need to set the state based on the previous state, read about the updater argument below. 如果需要根据以前的状态设置状态,请阅读下面的updater参数。

So it is considered a mistake in React to use this.state values together with setState because setState is asynchronous and may result in updating the state with wrong values (a demo ): 因此,在React this.state值与setState一起使用被认为是错误的,因为setState是异步的,并且可能导致使用错误的值更新状态( 演示 ):

// destructured
const { state, setState } = this;
setState({ foo: state.foo });

// destructured
const { foo } = this.state;
setState({ foo });

// undestructured
this.setState({ foo: this.state.foo });

While this would be proper way to update the state (a demo ): 虽然这是更新状态的正确方法( 演示 ):

// destructured
this.setState(({ foo }) => ({ foo }));

// undestructured
this.setState(state => ({ foo: state.foo }));

Is there ESLint rule or other way to prevent some or all of these cases where this.state can be misused? 有ESLint规则或者其他方式来阻止某些或所有这些情况下, this.state可以被滥用?

I assume it may be hard but possible to solve this case with static analysis. 我认为用静态分析来解决这个问题可能很困难。

If you use: 如果您使用:

// destructured
const { state, setState } = this;
setState({ foo: state.foo });

Eslint still warns you because of state.foo (accessing property of an object). 由于state.foo (访问对象的属性),Eslint仍会警告您。 To avoid this, you can define like: 为避免这种情况,您可以定义如下:

// destructured
const { state: { foo }, setState } = this;
setState({ foo });

But if you use: 但是如果你使用:

// undestructured
this.setState({ foo: this.state.foo });

Then, ESLINT will warn you to use destructuring syntax like: 然后,ESLINT将警告您使用解构语法,如:

const { foo } = this.state
this.setState({foo})

Note: since foo is the variable name to update and the name matches, we can use just {foo} and is same as {foo: foo} . 注意:由于foo是要更新的变量名,名称匹配,我们只能使用{foo}并且与{foo: foo}


Also, and however, I prefer to use this.setState() syntax rather than destructuring to this . 此外,与然而,我更喜欢使用this.setState()语法,而不是解构来this Because, in any application, we use this whenever necessary. 因为,在任何应用程序中,我们都会在必要时使用this And using const { ... } = this seems to be confusing if we look between the code when we see setState rather than this.setState . 并且使用const { ... } = this如果我们在看到setState而不是this.setState时查看代码, const { ... } = this似乎会让人感到困惑。 Thinking as of third developer. 思考第三开发者。


From the comments, you wanted to update the state one after another, then you should be using callback like: 从评论中,你想要一个接一个地更新状态,然后你应该使用回调,如:

onClick = () => {
   this.setState({ foo: 'Bar' }, () => {
      this.setState({ foo: this.state.foo + '!' });
   });
}

Now, you'll be able to see the changes to Hello Bar! 现在,您将能够看到Hello Bar!的更改Hello Bar! in your demo. 在你的演示中。

If you use setState like this: 如果你像这样使用setState:

onClick = () => {
   this.setState({ foo: 'Bar' })
   this.setState({ foo: this.state.foo + '!' });
   // obviously, better to use updater syntax though.
}

Then the first setState will be overridden by the last one. 然后第一个setState将被最后一个覆盖。 And you'll get the changes to Hello Foo! 你会得到Hello Foo!的变化Hello Foo! in your demo. 在你的演示中。

Also, the documentation states the same. 此外,文档陈述相同。 The updater syntax is just a handy method but results the same exactly as without the updater syntax. 更新程序语法只是一个方便的方法,但结果与没有更新程序语法完全相同。 The most important role is only with its callback syntax. 最重要的角色只有它的回调语法。 The callback syntax is used so that you can access the updated state right after its updates. 使用回调语法,以便您可以在更新后立即访问更新状态。


To know more about destructuring syntax. 要了解有关解构语法的更多信息。 You may follow my another post where, you can find detailed information and some links that will be a lot to be familiar. 您可以关注我的另一篇文章 ,您可以在其中找到详细信息和一些非常熟悉的链接。

eslint-plugin-react will do this check with react/no-access-state-in-setstate rule eslint-plugin-react将使用react / no-access-state-in-setstate规则进行检查

This rule should prevent usage of this.state inside setState calls. 此规则应阻止在setState调用中使用this.state。 Such usage of this.state might result in errors when two state calls are called in batch and thus referencing old state and not the current state. 当批量调用两个状态调用并因此引用旧状态而不是当前状态时,this.state的这种使用可能导致错误。

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

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