suchen

Heim  >  Fragen und Antworten  >  Hauptteil

将Array als Abhängigkeit in useEffect einbinden

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粉748218846P粉748218846408 Tage vor583

Antworte allen(2)Ich werde antworten

  • P粉464208937

    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])
    );
    

    现场演示

    Antwort
    0
  • P粉662802882

    P粉6628028822023-10-18 12:32:21

    您可以传递 JSON.stringify(outcomes) 作为依赖项列表:

    了解更多信息此处

    useEffect(() => {
      console.log(outcomes)
    }, [JSON.stringify(outcomes)])

    Antwort
    0
  • StornierenAntwort