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

React setState仅更新最后一个值?求助理解状态更新逻辑

React表单中多次调用setState仅最后一次生效的原因及修复方案

你遇到的问题核心在于React的state更新是异步批量处理,而且你每次调用setFilledIn时,都是基于handleSubmit函数执行瞬间的filledIn快照(也就是当前函数作用域里的初始state值)来做对象展开。比如你第一次修改firstName,第二次修改lastName时,依然是从原始的filledIn对象复制,而不是用上一次更新后的state,所以前两次的更新会被最后一次覆盖,最终只有age的修改生效。

下面提供两种可行的修复方案:

方法一:使用函数式更新

React的setState支持传入一个函数,这个函数会接收上一次更新后的state(prevState)作为参数,这样每次更新都能基于最新的state值操作:

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
  event.preventDefault();

  // 处理firstName
  if (firstNameRef.current == null || firstNameRef.current.value === "") {
    setFilledIn(prev => ({ ...prev, firstName: false }));
  } else {
    setFilledIn(prev => ({ ...prev, firstName: true }));
    person2.firstName = firstNameRef.current.value;
  }

  // 处理lastName
  if (lastNameRef.current == null || lastNameRef.current.value == "") {
    setFilledIn(prev => ({ ...prev, lastName: false }));
  } else {
    setFilledIn(prev => ({ ...prev, lastName: true }));
    person2.lastName = lastNameRef.current.value;
  }

  // 处理age
  if (ageRef.current == null || ageRef.current.value == "") {
    setFilledIn(prev => ({ ...prev, age: false }));
  } else {
    setFilledIn(prev => ({ ...prev, age: true }));
    person2.age = parseInt(ageRef.current.value);
  }
};

方法二:一次性收集所有更新,单次调用setState

更高效的方式是先判断所有字段的状态,把需要更新的属性收集到一个对象里,最后只调用一次setFilledIn,减少state更新次数:

const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
  event.preventDefault();
  
  const newFilledIn = { ...filledIn };

  // 处理firstName
  if (firstNameRef.current == null || firstNameRef.current.value === "") {
    newFilledIn.firstName = false;
  } else {
    newFilledIn.firstName = true;
    person2.firstName = firstNameRef.current.value;
  }

  // 处理lastName
  if (lastNameRef.current == null || lastNameRef.current.value == "") {
    newFilledIn.lastName = false;
  } else {
    newFilledIn.lastName = true;
    person2.lastName = lastNameRef.current.value;
  }

  // 处理age
  if (ageRef.current == null || ageRef.current.value == "") {
    newFilledIn.age = false;
  } else {
    newFilledIn.age = true;
    person2.age = parseInt(ageRef.current.value);
  }

  // 一次性更新state
  setFilledIn(newFilledIn);
};

两种方案的核心都是避免基于过期的state快照去更新,确保每次state修改都能正确叠加。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:22:19