知海

规则:set-state-in-render

ReactAPI 参考:ESLint 插件

规则:set-state-in-render

校验避免在渲染期间无条件设置 state,这可能会触发额外的渲染和潜在的无尽渲染循环。

规则详情

在渲染期间无条件调用 setState 会在当前渲染完成之前触发另一次渲染。这会创建一个无限循环,导致应用崩溃。

常见违规

无效

js 复制代码
// ❌ Unconditional setState directly in render
function Component({value}) {
  const [count, setCount] = useState(0);
  setCount(value); // Infinite loop!
  return <div>{count}</div>;
}

有效

js 复制代码
// ✅ Derive during render
function Component({items}) {
  const sorted = [...items].sort(); // Just calculate it in render
  return <ul>{sorted.map(/*...*/)}</ul>;
}

// ✅ Set state in event handler
function Component() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(count + 1)}>
      {count}
    </button>
  );
}

// ✅ Derive from props instead of setting state
function Component({user}) {
  const name = user?.name || '';
  const email = user?.email || '';
  return <div>{name}</div>;
}

// ✅ Conditionally derive state from props and state from previous renders
function Component({ items }) {
  const [isReverse, setIsReverse] = useState(false);
  const [selection, setSelection] = useState(null);

  const [prevItems, setPrevItems] = useState(items);
  if (items !== prevItems) { // This condition makes it valid
    setPrevItems(items);
    setSelection(null);
  }
  // ...
}

故障排查

我想将 state 同步到 prop

一个常见的问题是试图在 state 渲染后“修复”它。假设你想让计数器不超过 max prop:

js 复制代码
// ❌ Wrong: clamps during render
function Counter({max}) {
  const [count, setCount] = useState(0);

  if (count > max) {
    setCount(max);
  }

  return (
    <button onClick={() => setCount(count + 1)}>
      {count}
    </button>
  );
}

一旦 count 超过 max,就会触发无限循环。

相反,通常最好将此逻辑移至事件(state 首次被设置的地方)。例如,你可以在更新 state 时强制执行最大值:

js 复制代码
// ✅ Clamp when updating
function Counter({max}) {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(current => Math.min(current + 1, max));
  };

  return <button onClick={increment}>{count}</button>;
}

现在 setter 仅在响应点击时运行,React 正常完成渲染,且 count 永远不会超过 max

在极少数情况下,你可能需要根据先前渲染的信息调整 state。对于这些情况,请遵循 此模式 有条件地设置 state。

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。