Heim > Fragen und Antworten > Hauptteil
Alle 5 Sekunden gehen Daten aus der langen Abfrage ein und ich möchte, dass meine Komponente jedes Mal einen Vorgang auslöst, wenn sich ein Element des Arrays (oder die Array-Länge selbst) ändert. Wie verhindere ich, dass useEffect beim Übergeben eines Arrays als Abhängigkeit in eine Endlosschleife gerät, es aber trotzdem schaffe, einige Vorgänge zu planen, wenn sich ein Wert ändert?
useEffect(() => { console.log(outcomes) }, [outcomes])
wobei outcomes
是一个 ID 数组,例如 [123, 234, 3212]
。数组中的项目可能会被替换或删除,因此数组的总长度可能(但不一定)保持不变,因此传递 outcomes.length
als Abhängigkeit nicht der Fall ist.
outcomes
Benutzerdefinierter Selektor aus Neuauswahl:
const getOutcomes = createSelector( someData, data => data.map(({ outcomeId }) => outcomeId) )
P粉4642089372023-10-18 15:49:11
使用 JSON.stringify() 或任何深度比较方法可能效率较低,如果您提前知道对象的形状,您可以编写自己的效果钩子来根据结果触发回调您的自定义相等函数。
useEffect
的工作原理是检查依赖项数组中的每个值是否与前一渲染中的值相同,如果其中一个不是,则执行回调。因此,我们只需要使用 useRef
保留我们感兴趣的数据实例,并且仅在自定义相等性检查返回 false
时分配一个新实例来触发效果。
function arrayEqual(a1: any[], a2: any[]) { if (a1.length !== a2.length) return false; for (let i = 0; i < a1.length; i++) { if (a1[i] !== a2[i]) { return false; } } return true; } type MaybeCleanUpFn = void | (() => void); function useNumberArrayEffect(cb: () => MaybeCleanUpFn, deps: number[]) { const ref = useRef(deps); if (!arrayEqual(deps, ref.current)) { ref.current = deps; } useEffect(cb, [ref.current]); }
function Child({ arr }: { arr: number[] }) { useNumberArrayEffect(() => { console.log("run effect", JSON.stringify(arr)); }, arr); return{JSON.stringify(arr)}; }
更进一步,我们还可以通过创建一个接受自定义相等函数的效果钩子来重用该钩子。
type MaybeCleanUpFn = void | (() => void); type EqualityFn = (a: DependencyList, b: DependencyList) => boolean; function useCustomEffect( cb: () => MaybeCleanUpFn, deps: DependencyList, equal?: EqualityFn ) { const ref = useRef(deps); if (!equal || !equal(deps, ref.current)) { ref.current = deps; } useEffect(cb, [ref.current]); }
useCustomEffect( () => { console.log("run custom effect", JSON.stringify(arr)); }, [arr], (a, b) => arrayEqual(a[0], b[0]) );
P粉6628028822023-10-18 12:32:21
您可以传递 JSON.stringify(outcomes)
作为依赖项列表:
了解更多信息此处
useEffect(() => { console.log(outcomes) }, [JSON.stringify(outcomes)])