创见博客
useState为什么推荐使用函数式更新
七崽爱吃小饼干2026/01/06阅读 0专栏 React

一、先理解什么是函数式更新

在使用 useState 时,更新状态有两种方式:

  1. 直接更新:直接传入新值(如 setCount(count + 1))
  2. 函数式更新:传入一个函数,函数的参数是当前最新的状态值,返回新状态(如 setCount(prevCount => prevCount + 1))

二、函数式更新的核心好处

1. 确保使用最新的状态值(解决状态滞后问题)

React 的状态更新是异步批量处理的,当你在事件处理、定时器、异步操作中多次更新状态时,直接更新可能会“捕获”到旧的状态值,导致更新结果不符合预期。

示例:直接更新的问题

jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    // 异步批量更新中,这里的 count 始终是点击时的初始值(比如 0)
    setCount(count + 1); 
    setCount(count + 1); 
    // 最终 count 只会变成 1,而不是预期的 2
  };

  return <button onClick={handleClick}>Count: {count}</button>;
}

函数式更新的解决方案

jsx
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    // 函数式更新会拿到上一次更新后的最新值
    setCount(prevCount => prevCount + 1); 
    setCount(prevCount => prevCount + 1); 
    // 最终 count 会变成 2,符合预期
  };

  return <button onClick={handleClick}>Count: {count}</button>;
}

2. 处理依赖于前一个状态的更新

当新状态完全依赖于旧状态时,函数式更新是更可靠的方式——它显式地声明“新状态基于最新的旧状态计算”,避免因闭包捕获旧值导致的错误。

比如处理数组/对象状态时:

jsx
// 错误:直接更新可能使用旧的 list 引用
setList([...list, newItem]);

// 正确:函数式更新确保拿到最新的 list
setList(prevList => [...prevList, newItem]);

3. 代码语义更清晰

函数式更新明确表达了“状态更新依赖于前一个状态”的逻辑,让代码意图更易读、易维护。

总结

  1. 核心优势:解决异步更新中“状态滞后”问题,确保使用最新的状态值计算新状态。
  2. 适用场景:多次连续更新状态、状态更新依赖于旧状态(如计数、数组追加)、异步操作中更新状态。
  3. 语义清晰:显式声明“基于旧状态更新”,提升代码可读性和可维护性。

简单来说,只要你的新状态依赖于旧状态,就优先使用函数式更新,这是 React 官方推荐的最佳实践。

评论
0/100