分享
2.使用 useState 的函数式更新方式能带来哪些好处?
输入“/”快速插入内容
2.使用 useState 的函数式更新方式能带来哪些好处?
用户8691
用户8691
2025年9月16日修改
useState
:为什么函数式更新更可靠?
在日常的 React 开发中,
useState
是我们最亲密的伙伴之一。我们通常会这样使用它:
代码块
JavaScript
const [count, setCount] = useState(0);
const handleIncrement = () => {
setCount(count + 1); // 直接传入一个新值
};
这种
setCount(newValue)
的方式直观且易于理解。然而,
useState
还提供了另一种看似稍显繁琐的更新模式——函数式更新:
代码块
JavaScript
const [count, setCount] = useState(0);
const handleIncrement = () => {
setCount(prevCount => prevCount + 1); // 传入一个函数
};
既然已经有了直接更新的方式,为什么 React 还要提供函数式更新呢?它仅仅是一种语法偏好,还是背后蕴含着更深层的原因?
答案是后者。在某些特定场景下,函数式更新不仅是“更好”的选择,甚至是“唯一正确”的选择。它能帮助我们有效规避一类因 State 闭包陷阱(Stale Closure)导致的常见 Bug。
问题浮现:当 State 更新不符合预期
让我们从一个简单的反例开始。假设我们需要在一次交互中,连续两次将
count
的值加一。很多人会很自然地写出以下代码:
代码块
JavaScript
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const handleTripleIncrement = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleTripleIncrement}>Increment by 3</button>
</div>
);
}
直觉上,每次点击按钮,
count
应该会增加 3。但实际运行后你会发现,
count
每次只增加了 1。
这背后的本质原因是:
setCount
的更新是异步的,并且 React 会对短时间内连续的更新进行批处理(Batching)。
在
handleTripleIncrement
函数的执行上下文中,
count
的值始终是当次渲染时的快照。当我们连续三次调用
setCount(count + 1)
时,对于 React 而言,它收到的指令是: