初级开发者在使用组件状态时常犯的 3 个 React 错误 3 - 这个错误最让人抓狂,除非你找到原因。React 也让我在日常生活中思考异步问题😅

2025-05-28

初级开发人员在 React 组件状态中常犯的 3 个错误

3 - 这个错误最让人抓狂,除非你找到原因。React 也让我在日常生活中思考异步问题😅

我最喜欢 Web 开发的一点就是总有新东西要学。你可能穷尽一生去掌握各种编程语言、库和框架,却仍然无法完全掌握它们。

因为我们都在学习,所以也意味着我们都容易犯错。这没关系。我们的目标是不断进步,不断进步。如果你犯了错误并从中吸取教训,那你做得很好!但如果你没有学到任何新东西,而是不断重复同样的错误,那么……你的职业生涯可能停滞不前了。

本着这种精神,以下是我在代码审查过程中看到的初级开发人员在处理 React 组件状态时经常犯的三个常见错误。我们将逐一分析每个错误,并讨论如何修复它们。


1. 直接修改状态

更改组件状态时,务必返回包含修改内容的新状态副本,而不是直接修改当前状态。如果您错误地修改了组件的状态,React 的 diffing 算法将无法捕获该更改,从而导致组件无法正确更新。我们来看一个例子。

假设您有如下状态:

this.state = {
  colors: ['red', 'green', 'blue']
}
Enter fullscreen mode Exit fullscreen mode

现在你想将颜色“黄色”添加到这个数组中。你可能想这样做:

this.state.colors.push('yellow')
Enter fullscreen mode Exit fullscreen mode

甚至这样:

this.state.colors = [...this.state.colors, 'yellow']
Enter fullscreen mode Exit fullscreen mode

但这两种方法都是错误的!在类组件中更新状态时,你总是需要使用该setState方法,并且应该始终小心不要改变对象。以下是将元素添加到数组的正确方法:

this.setState(prevState => ({ colors: [...prevState.colors, 'yellow'] }))
Enter fullscreen mode Exit fullscreen mode

这直接导致了我们的第二个错误。


2. 不使用函数来设置依赖于先前状态的状态

该方法有两种使用方式setState。第一种是提供一个对象作为参数。第二种是提供一个函数作为参数。那么,什么时候应该使用其中一种呢?

例如,如果你有一个可以启用或禁用的按钮,你可能会有一个名为 的状态,isDisabled它保存一个布尔值。如果你想将按钮从启用状态切换到禁用状态,你可能会想写这样的代码,使用一个对象作为参数:

this.setState({ isDisabled: !this.state.isDisabled })
Enter fullscreen mode Exit fullscreen mode

那么,这有什么问题呢?问题在于 React 状态更新可以批量处理,这意味着单个更新周期内可能会发生多个状态更新。如果您的更新是批量处理的,并且启用/禁用状态有多个更新,最终结果可能与您预期的不一样。

这里更新状态的更正确方法是提供先前状态的函数作为参数:

this.setState(prevState => ({ isDisabled: !prevState.isDisabled }))
Enter fullscreen mode Exit fullscreen mode

现在,即使您的状态更新是分批的,并且对启用/禁用状态的多次更新是一起进行的,每次更新都将依赖于正确的先前状态,以便您始终能够获得期望的结果。

对于诸如增加计数器之类的操作来说也是如此。

不要这样做:

this.setState({ counterValue: this.state.counterValue + 1 })
Enter fullscreen mode Exit fullscreen mode

执行以下操作:

this.setState(prevState => ({ counterValue: prevState.counterValue + 1 }))
Enter fullscreen mode Exit fullscreen mode

这里的关键是,如果新状态依赖于旧状态的值,则应始终使用函数作为参数。如果要设置不依赖于旧状态的值,则可以使用对象作为参数。


3. 忘记setState异步

最后,需要记住的是,这setState是一个异步方法。例如,假设我们有一个状态如下的组件:

this.state = { name: 'John' }
Enter fullscreen mode Exit fullscreen mode

然后我们有一个方法来更新状态,然后将状态记录到控制台:

this.setState({ name: 'Matt' })
console.log(this.state.name)
Enter fullscreen mode Exit fullscreen mode

你可能以为这会打印'Matt'到控制台,但事实并非如此!它打印了'John'

原因在于,它又setState是异步的。这意味着当它调用 setState 时,状态更新才会开始,但由于异步代码是非阻塞的,所以它下面的代码将继续执行。

如果您有需要在状态更新后运行的代码,React 允许您提供一个在更新完成后运行的回调函数。

更新后记录当前状态的正确方法是:

this.setState({ name: 'Matt' }, () => console.log(this.state.name))
Enter fullscreen mode Exit fullscreen mode

好多了!现在它能'Matt'按预期正确记录了。


结论

好了!三个常见错误以及如何改正它们。记住,犯错是可以的。你在学习。我在学习。我们都在学习。让我们继续学习,一起进步。

(如果您理解封面图片的参考意义,则可获得加分。)


补充:经常有人问我,我在本文中概述的原则是否也适用于函数组件和钩子。我决定写一篇后续文章,专门讨论这些!你可以在这里找到它:

https://dev.to/thawkin3/3-mistakes-junior-developers-make-with-react-function-component-state-88a

文章来源:https://dev.to/thawkin3/3-react-mistakes-junior-developers-make-with-component-state-1bhd
PREV
大幅减少代码审查时间的 7 种方法 1:保持拉取请求 (Pull Request) 较小 1:保持拉取请求 (Pull Request) 较小
NEXT
程序员必须具备的7个习惯!