如何在 React 中正确地使用 useEffect 来监听对象或数组依赖项的变化,避免无限循环或无效渲染?
如何在 React 中正确地使用 useEffect 来监听对象或数组依赖项的变化,避免无限循环或无效渲染?
回答与解析:
在 React 中,useEffect 的依赖数组如果包含对象、数组等引用类型,即使内容未变,每次渲染时这些值的引用地址都会不同,从而导致 useEffect 重复执行,甚至引发无限循环。
常见错误示例:
useEffect(() => {
fetchData();
}, [{ id: 1 }]); // 每次渲染都创建新对象,导致无限触发
正确做法:
-
确保依赖项是稳定引用:
- 使用原始类型(如 number、string)作为依赖;
- 或将对象/数组提升到组件外部(如用 useMemo 缓存)。
-
使用 useMemo 缓存复杂依赖:
const config = useMemo(() => ({ id: 1 }), []); // 仅在首次渲染创建
useEffect(() => {
fetchData(config);
}, [config]);
- 对于函数依赖,使用 useCallback:
const fetchData = useCallback(async (id) => {
// ...
}, []);
useEffect(() => {
fetchData(1);
}, [fetchData]);
- 必要时自定义比较逻辑:
- 若需深度比较对象内容,可结合 usePrevious + lodash.isEqual 实现自定义 useEffect 行为。
总结:useEffect 对依赖项使用严格相等(===)比较,引用类型需保证引用稳定,否则会误判为“变化”。合理使用 useMemo 和 useCallback 是避免此类问题的关键。

发表评论 (审核通过后显示评论):