setState()并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用setState()之后立即读取this.state可能是一个陷阱。而是使用componentDidUpdate或setState回调(setState(updater,callback)),确保在应用更新后均能触发这两种方法。如果需要基于先前的状态来设置状态,请阅读以下有关updater参数的信息。
因此在React中将this.state
值与setState
一起使用被认为是错误的,因为setState
是异步的,可能会导致使用错误的值更新状态({{3 }):
// destructured
const { state, setState } = this;
setState({ foo: state.foo });
// destructured
const { foo } = this.state;
setState({ foo });
// undestructured
this.setState({ foo: this.state.foo });
虽然这是更新状态(demo)的正确方法:
// destructured
this.setState(({ foo }) => ({ foo }));
// undestructured
this.setState(state => ({ foo: state.foo }));
是否存在ESLint规则或其他方法来防止其中某些{\ {1}}被滥用的情况?
我认为可能很难,但可以通过静态分析解决此问题。
答案 0 :(得分:3)
如果您使用:
// destructured
const { state, setState } = this;
setState({ foo: state.foo });
Eslint仍然由于state.foo
(访问对象的属性)而警告您。为了避免这种情况,您可以定义如下:
// destructured
const { state: { foo }, setState } = this;
setState({ foo });
但是,如果您使用:
// undestructured
this.setState({ foo: this.state.foo });
然后,ESLINT将警告您使用诸如以下的解构语法:
const { foo } = this.state
this.setState({foo})
请注意:由于foo
是要更新的变量名并且名称匹配,因此我们只能使用{foo}
并与{foo: foo}
相同。
而且,但是,我更喜欢使用this.setState()
语法,而不是解构为this
。因为在任何应用程序中,我们都会在必要时使用this
。如果在看到const { ... } = this
而不是setState
时在代码之间看,使用this.setState
似乎会造成混淆。从第三位开发者开始思考。
从注释中,您想要一个接一个地更新状态,那么您应该使用回调:
onClick = () => {
this.setState({ foo: 'Bar' }, () => {
this.setState({ foo: this.state.foo + '!' });
});
}
现在,您将可以在演示中看到对Hello Bar!
的更改。
如果您这样使用setState:
onClick = () => {
this.setState({ foo: 'Bar' })
this.setState({ foo: this.state.foo + '!' });
// obviously, better to use updater syntax though.
}
然后,第一个setState将被最后一个setState覆盖。然后,您将在演示中对Hello Foo!
进行更改。
此外,文档指出相同。 updater语法只是一种方便的方法,但其结果与没有updater语法的结果完全相同。最重要的作用仅在于其回调语法。使用回调语法,以便您可以在更新后的状态立即访问。
了解有关解构语法的更多信息。您可以关注my another post,在这里您可以找到详细的信息和一些熟悉的链接。
答案 1 :(得分:2)
eslint-plugin-react将按照react/no-access-state-in-setstate规则进行检查
此规则应防止在setState调用中使用this.state。当批量调用两个状态调用并因此引用旧状态而不是当前状态时,this.state的这种用法可能会导致错误。