防止 this.state 与 setState 一起使用

IT技术 javascript reactjs eslint static-analysis
2021-05-11 12:17:07

参考文献指出:

setState() 并不总是立即更新组件。它可能会批量更新或推迟更新。这使得在调用 setState() 后立即读取 this.state 成为一个潜在的陷阱。相反,使用 componentDidUpdate 或 setState 回调 (setState(updater, callback)),这两者都保证在应用更新后触发。如果您需要根据之前的状态设置状态,请阅读下面的更新程序参数。

所以在 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 });

虽然这将是更新状态的正确方法(演示):

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

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

是否有 ESLint 规则或其他方法来防止这些this.state可能被滥用的部分或全部情况

我认为这可能很难,但可以通过静态分析解决这种情况。

2个回答

eslint-plugin-react将使用react/no-access-state-in-setstate规则进行此检查

此规则应防止在 setState 调用中使用 this.state。当批量调用两个状态调用并因此引用旧状态而不是当前状态时,this.state 的这种用法可能会导致错误。

如果您使用:

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

由于state.foo(访问对象的属性),Eslint 仍然会警告您为避免这种情况,您可以定义如下:

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

但是如果你使用:

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

然后,ESLINT 会警告你使用解构语法,例如:

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

注意:由于foo是要更新的变量名称并且名称匹配,因此我们可以使用 just{foo}和 is 相同{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 将被最后一个覆盖。您将Hello Foo!在演示中获得更改

此外,文档说明相同。更新程序语法只是一种方便的方法,但结果与没有更新程序语法的情况完全相同。最重要的作用仅在于其回调语法。使用回调语法,以便您可以在更新后立即访问更新的状态。


了解有关解构语法的更多信息。你可以关注我的另一篇文章,在那里你可以找到详细的信息和一些很熟悉的链接。