React 中的函数式更新

React 中的函数式更新

React 中的函数式更新 ,指的是在更新 state 时,不给 setState 直接传新值,而是传一个函数 。这个函数会接收上一次最新的 state ,再基于它计算出新的 state。

基本写法

jsx 复制代码
setCount(prev => prev + 1);

这里的:

  • prev:上一次最新的状态值
  • prev + 1:基于旧值计算新值

为什么要用函数式更新?

因为 React 的状态更新可能是异步的、批量的。

如果你直接这样写:

jsx 复制代码
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);

你以为会加 3,实际上很多情况下只会加 1。

因为这 3 次拿到的 count 很可能都是同一个旧值。

而函数式更新:

jsx 复制代码
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);

React 会按顺序执行:

  • 第一次:0 -> 1
  • 第二次:1 -> 2
  • 第三次:2 -> 3

这样结果才是对的。


什么时候特别适合用?

1. 新状态依赖旧状态

最典型。

jsx 复制代码
setAge(prev => prev + 1);
setList(prev => [...prev, newItem]);

2. 连续多次更新同一个状态

jsx 复制代码
setCount(prev => prev + 1);
setCount(prev => prev + 1);

3. 异步回调里更新状态

比如:

  • setTimeout
  • Promise
  • useEffect
  • 事件订阅回调
jsx 复制代码
setTimeout(() => {
  setCount(prev => prev + 1);
}, 1000);

这样更安全,因为你拿到的是最新状态,不是闭包里的旧值。


对象状态中的函数式更新

如果 state 是对象,常见写法是:

jsx 复制代码
setState(prev => ({
  ...prev,
  count: 10
}));

含义是:

  • 先把旧对象展开
  • 再覆盖你要修改的字段

例如:

jsx 复制代码
const [user, setUser] = useState({
  name: 'Tom',
  age: 20
});

setUser(prev => ({
  ...prev,
  age: 21
}));

结果:

jsx 复制代码
{ name: 'Tom', age: 21 }

为什么不能直接改原对象?

jsx 复制代码
user.age = 21;
setUser(user);

这样是直接修改原对象,引用没变,React 可能识别不到变化。

而函数式更新通常配合不可变写法:

jsx 复制代码
setUser(prev => ({
  ...prev,
  age: 21
}));

会返回一个新对象,React 更容易正确触发更新。


一句话理解

函数式更新就是:

"别相信你手里的旧 state,找 React 要最新的 state,再算出新值。"


什么时候用普通写法,什么时候用函数式更新?

普通写法

当新值不依赖旧值时可以直接写:

jsx 复制代码
setTheme('dark');
setVisible(true);

函数式更新

当新值依赖旧值时,优先用:

jsx 复制代码
setCount(prev => prev + 1);
setItems(prev => [...prev, item]);

总结

公式记住就行

  • 不依赖旧状态:直接传值
  • 依赖旧状态:传函数

最常见示例

jsx 复制代码
setCount(prev => prev + 1);
setList(prev => [...prev, newItem]);
setState(prev => ({ ...prev, loading: false }));

转载:https://www.toutiao.com/item/7626739884350390830/

相关推荐
ZoeLandia5 小时前
React03:useState 与不可变更新
前端·react.js·typescript·react
莫逸风1 天前
【毕设源码二期01】校园失物招领系统:从发布线索到核验交接
spring boot·毕业设计·课程设计·react
Shockang4 天前
TanStack Router 实战:URL 校验、Loader 与路由权限
typescript·react·路由·前端开发·tanstack router
小天源7 天前
智叟云集系统架构解析:从品牌 AI 可见度监测到前后端协同
人工智能·react.js·系统架构·node.js·react·ai监测·ai品牌监测
guslegend11 天前
工程地基、Provider 与 ReAct 循环:Agent 核心能力的设计、实现与验收
人工智能·agent·react·架构设计·spring ai
EatFan12 天前
React 项目踩坑实录:useEffect 闭包陷阱、Context 性能陷阱与 React 18 升级避坑排查手册
前端·javascript·react.js·react·react hooks·useeffect·闭包陷阱
FungLeo17 天前
成为全栈·Next.js 网站前台篇·站点设置如何驱动页头、页脚与 SEO
react·isr·next.js·metadata·成为全栈·站点配置
大连好光景17 天前
ReAct的原理?与CoT的区别是啥?
react·cot
大连好光景17 天前
Agent完整工作过程
react·agent完整工作流程
FungLeo19 天前
成为全栈·Next.js 网站前台篇·同源 BFF 代理:API、附件、Cookie 与跨站写入保护
react·csrf·next.js·bff·成为全栈·route handler