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

React调和机制异常:组件状态为何重置情况不一致?

React组件位置变化时的状态保留差异问题

我在React官方文档中看到一个重置状态的示例,为理解该示例,将其简化为多个实验,但无法解释观察到的结果。

所有实验均使用同一版本的Counter组件:

function Counter() {
  const [score, setScore] = useState(0);

  useEffect(() => {
    const i = setInterval(() => setScore((n) => n + 1), 200);
    return () => clearInterval(i);
  }, []);
  return <div>{score}</div>;
}

Counter挂载后会快速计数,卸载再挂载时状态会重置为0。

实验一:Counter包裹在有状态容器中

export default function Scoreboard() {
  const [bool, setBool] = useState(true);
  return (
    <div>
      {bool && <Counter />}
      {!bool && <Counter />}
      <button
        onClick={() => {
          setBool(!bool);
        }}
      >
        Switch
      </button>
    </div>
  );
}

点击“Switch”时,Counter状态会重置。

实验二:重构后的直观版本

export default function Scoreboard() {
  const [bool, setBool] = useState(false);
  return (
    <div>
      {bool ? (
        <>
          <div />
          <Counter />
        </>
      ) : (
        <>
          <Counter />
          <div />
        </>
      )}
      <button
        onClick={() => {
          setBool(!bool);
        }}
      >
        Switch
      </button>
    </div>
  );
}

点击“Switch”时,Counter状态依然会重置。

基于前两个实验,我初步认为:组件位置变化时状态不会保留。但日常开发中,动态列表后跟随有状态元素并未出现此情况,于是做了第三个实验。

实验三:动态列表后跟随Counter

export default function Scoreboard() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <>
        {Array(count)
          .fill(0)
          .map(() => (
            <div>a</div>
          ))}
        <Counter />
      </>
      <button
        onClick={() => {
          setCount((n) => n + 1);
        }}
      >
        Switch
      </button>
    </div>
  );
}

令人惊讶的是,每次点击“Switch”,Counter位置变化,但状态从未重置。

问题

为何前两个示例中状态未保留,第三个却保留?所有案例中仅Counter相对兄弟元素的位置发生变化。

补充说明:所有案例均未指定key,默认使用索引。不同位置调用JSX元素不会赋予不同标识,否则第一个示例中状态不会重置。我知道添加key可改变此行为,但想理解这种行为差异的根本原因。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:00:35