You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用React的set状态函数时,React会对传入的对象做克隆处理吗?

问题解答

核心结论

  • 你写的用法不安全,修改已经传给setUser的克隆对象,本质就是直接修改当前状态
  • React不会对你传入set函数的对象做任何二次克隆,会直接存储该对象的引用作为新状态
  • 不需要每次都额外深克隆,只要保证每次传给set函数的都是一个全新的、没有被后续修改的对象即可

具体逻辑说明

你第一次执行setUser(newUser)之后,React内部存储的user状态就和你手里的newUser变量指向了同一个内存对象。此时你修改newUser.email,等于直接修改了当前的user状态值,这违反了React状态不可变的原则,可能会引发两个问题:

  1. 状态会在你意料之外的时机被修改,可能引发渲染逻辑异常
  2. 你后续调用setUser(newUser)时,React的默认浅比较会判定新旧状态是同一个引用,直接跳过这次更新,导致视图不会刷新最新的email值

正确写法推荐

方案1:每次更新都生成新的对象

const [user, setUser] = useState({ name: '', email: '' })

// 第一次更新
const newUser = cloneDeep(user)
newUser.name = 'Steve'
setUser(newUser)
// 这里用完就不要再操作newUser了

// 异步操作后第二次更新
const updatedUser = cloneDeep(user) // 重新克隆最新的状态
updatedUser.email = 'steve@example.com'
setUser(updatedUser)

方案2:用函数式更新避免依赖外部状态引用(更推荐)

如果异步操作间隔时间较长,可能存在状态已经被其他逻辑修改的情况,用函数式更新可以直接拿到最新的状态值,更稳妥:

const [user, setUser] = useState({ name: '', email: '' })

// 第一次更新
setUser(prev => {
  const newUser = cloneDeep(prev)
  newUser.name = 'Steve'
  return newUser
})

// 异步操作后第二次更新
setUser(prev => {
  const updatedUser = cloneDeep(prev)
  updatedUser.email = 'steve@example.com'
  return updatedUser
})

内容的提问来源于stack exchange,提问作者Glenn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 20:18:02