
规则:set-state-in-effect
ReactAPI 参考:ESLint 插件
规则:set-state-in-effect
校验避免在 effect 中同步调用 setState,这可能导致重新渲染并降低性能。
规则详情
在 effect 中立即设置 state 会迫使 React 重新启动整个渲染周期。当你在 effect 中更新 state 时,React 必须重新渲染你的组件、将更改应用到 DOM,然后再次运行 effects。这产生了一次额外的渲染过程,而通过在渲染期间直接转换数据或从 props 派生 state 本可以避免。改为在组件顶层转换数据。这样代码会在 props 或 state 更改时自然重新运行,而不会触发额外的渲染周期。
effect 中的同步 setState 调用会在浏览器绘制之前触发立即重新渲染,导致性能问题和视觉卡顿。React 必须渲染两次:一次应用 state 更新,然后在 effects 运行后再次渲染。当相同的结果可以通过单次渲染实现时,这种双重渲染是浪费的。
在许多情况下,你可能根本不需要 effect。请参阅 你可能不需要 Effect 了解更多信息。
常见违规
此规则捕获了几种不必要使用同步 setState 的模式:
- 同步设置 loading state
- 在 effects 中从 props 派生 state
- 在 effects 中转换数据,而不是在渲染期间
无效
此规则的不正确代码示例:
js
// ❌ Synchronous setState in effect
function Component({data}) {
const [items, setItems] = useState([]);
useEffect(() => {
setItems(data); // Extra render, use initial state instead
}, [data]);
}
// ❌ Setting loading state synchronously
function Component() {
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true); // Synchronous, causes extra render
fetchData().then(() => setLoading(false));
}, []);
}
// ❌ Transforming data in effect
function Component({rawData}) {
const [processed, setProcessed] = useState([]);
useEffect(() => {
setProcessed(rawData.map(transform)); // Should derive in render
}, [rawData]);
}
// ❌ Deriving state from props
function Component({selectedId, items}) {
const [selected, setSelected] = useState(null);
useEffect(() => {
setSelected(items.find(i => i.id === selectedId));
}, [selectedId, items]);
}
有效
此规则的正确代码示例:
js
// ✅ setState in an effect is fine if the value comes from a ref
function Tooltip() {
const ref = useRef(null);
const [tooltipHeight, setTooltipHeight] = useState(0);
useLayoutEffect(() => {
const { height } = ref.current.getBoundingClientRect();
setTooltipHeight(height);
}, []);
}
// ✅ Calculate during render
function Component({selectedId, items}) {
const selected = items.find(i => i.id === selectedId);
return <div>{selected?.name}</div>;
}
当某些东西可以从现有的 props 或 state 计算得出时,不要将其放入 state。 相反,在渲染期间计算它。这会使你的代码更快、更简单、更不容易出错。在 你可能不需要 Effect 中了解更多。
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
