React_为什么说useState的setState是异步的

  • React 在响应用户交互或事件时,会将多次状态更新合并(batching)并延后到下一次渲染中一起执行。这意味着当你调用 setState(或 useState 的 setter)后,状态并不会立即更新到最新值,而是在 React 下一轮更新阶段才生效。这样的设计可以减少不必要的重渲染,提升性能,但也带来了“看似异步”的特性。

可能造成的问题:

const [count, setCount] = useState(0)

function handleClick() {
  setCount(count + 1)
  console.log(count) // 第一次点击时, 这里会打印0, 第二次点击时会打印1, 因为对数据的修改是异步的, 因此这段代码读取的永远是当前值
}
const [count, setCount] = useState(0)

function handleClick() {
  // 理论上想 +1,然后再 +1,变成 2
  setCount(count + 1)
  setCount(count + 1) // 因为读取的永远是旧值, 因此即便写了两次对源值的修改, 但是都是对之前同一值的修改, 多段代码与同一段代码的作用是一样的
  console.log(count)  // 第一次点击时打印0, 第二次点击时打印1
}

解决方法

  • 在副作用里读取最新值 如果需要在 state 更新后执行某些逻辑,可以放到 useEffect 里监听:
const [count, setCount] = useState(0)

function handleClick() {
  setCount(count + 1)
}
useEffect(() => {
  console.log(count)
}, [count])
  • 在同一函数中做多次修改时使用函数式更新
const [count, setCount] = useState(0)

function handleClick() {
  setCount(count => count + 1)
  setCount(count => count + 1)
}
useEffect(() => {
  console.log(count) // 每次点击分别打印2,4,6,8
}, [count])
  • 利用 useRef 保存最新值 当你要在事件外或不想依赖重渲染的场景下,记录最新状态:
const [count, setCount] = useState(0)
const countRef = useRef(0)

function handleClick() {
  countRef.current += 1
  setCount(countRef.current)
  console.log(countRef.current) // 直接用 ref 拿到最新
}
posted @ 2025-07-20 11:02  Syinho  阅读(35)  评论(0)    收藏  举报