返回

setState真的是异步吗?

前端

“setState() 是异步的”,这句话在React中几乎已经成为了一个“教条”,大多数开发人员在阅读文档时都会遇到这样的

setState() 是异步的。这也就是说,它在立即调用后不会立即生效。相反,下一次渲染时才生效。

有人看到这句话可能会发出如下疑问:“异步执行不是很难实现吗?为什么要在React中做这种妥协?”,实际上,这一妥协是经过深思熟虑的,它带来了如下几个好处:

  • 批量更新: React 会将多次setState() 合并成一次渲染,从而提高性能,降低不必要的UI重新渲染次数。
  • 事务性更新: React 会保证所有的setState() 都在同一时间应用,这使得状态更新更加可预测,更容易调试。

然而,“setState() 是异步的”这句话也经常引起一些困惑。最常见的一个问题是:“为什么在组件首次渲染时,我setState(),会导致在UI中看不到任何变化?”,原因在于,在组件首次渲染时,setState() 是同步执行的,而不是异步的,这是为了确保组件在初始渲染时具有正确的状态。

那么,什么时候setState() 是异步执行的呢?只有在组件更新时,setState() 才是异步执行的。如果你在componentDidUpdate() 生命周期函数中调用setState(),那么它将是异步执行的。

另一个常见的问题是:“为什么在组件更新时,我setState(),会导致UI多次重新渲染?”,原因在于,在组件更新时,setState() 是异步执行的,这意味着它不会立即生效。在setState() 被调用后,React会将该组件标记为“脏”,并计划在下一次渲染时重新渲染它。如果在此期间你再次调用setState(),那么React会将该组件再次标记为“脏”,并计划在下一次渲染时重新渲染它。如此循环往复,就会导致UI多次重新渲染。

解决方法

要解决这个问题,你可以使用useCallback()或useMemo() hook来缓存组件的某些部分,从而减少不必要的重新渲染。你还可以使用Redux或其他状态管理库来管理组件的状态,从而避免在组件内部调用setState()。

结论

setState() 是一个异步的方法,它可以在组件首次渲染时和组件更新时被调用。在组件首次渲染时,setState() 是同步执行的,而在组件更新时,setState() 是异步执行的。异步执行setState() 的优点是,可以提高性能和降低不必要的UI重新渲染次数。缺点是,可能会导致UI多次重新渲染。要解决这个问题,可以使用useCallback()或useMemo() hook来缓存组件的某些部分,或者使用Redux或其他状态管理库来管理组件的状态。