何解无限循环之困?useEffect具物与数组
技术之解
问题之由,在于此也。useEffect较之诸依赖。参照比较(===),非内容所限。尔用之useState({}),每有呼召setObj({})创之新物入内存虽内容无异,然 React 洞察其引用已易。obj !== obj复施其效,遂成无穷之环。
尔之事:
const [ingredients, setIngredients] = useState({});
useEffect(() => {
setIngredients({}); // ← ¡Crea un nuevo objeto!
}, [ingredients]); // ← Siempre es una referencia diferente → bucle infinito
终解之法(三途)
选项一:用函数式状态+深度比较(推荐)
useEffect(() => {
setIngredients(prev => {
// Solo actualiza si el contenido realmente cambió
if (Object.keys(prev).length > 0) {
return {};
}
return prev;
});
}, []); // ← Sin dependencias: solo ejecuta al montar
选项二:手动对比内容与useDeepCompareEffect
// Implementa una comparación profunda personalizada
function useDeepCompareEffect(callback, dependencies) {
useEffect(() => {
callback();
}, [dependencies.map(dep => JSON.stringify(dep))]);
}
// Uso:
useDeepCompareEffect(() => {
setIngredients({});
}, [ingredients]);
选项三:用useReducer处理复杂逻辑(最佳实践)
const initialState = {};
function reducer(state, action) {
switch (action.type) {
case 'reset':
return {};
default:
return state;
}
}
const [ingredients, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
dispatch({ type: 'reset' });
}, []); // ← Sin dependencias
修正代码块(推荐)
import { useState, useEffect } from 'react';
function MyComponent() {
const [ingredients, setIngredients] = useState({});
useEffect(() => {
// Solo resetea si el objeto no está vacío
setIngredients(prev =>
Object.keys(prev).length > 0 ? {} : prev
);
}, []); // ← Sin dependencias para evitar bucles
return (
<div>
<p>Ingredients: {JSON.stringify(ingredients)}</p>
</div>
);
}
小贴士:useEffect
中对象与数组的黄金法则,勿将对象/数组直接置于依赖中,若于效果内创建新对象/数组。
:
- 若逻辑仅需于挂载/卸载时执行,
[];- 动态依赖,宜用深度比较;
- ;
useReducer复杂状态,当细思之;- ;
ingredients.length简单校验,宜较特定属性(如:__JHSNS_SEG_db611950_39__,非数组全量)。























