← Wszystkie zadaniaReact · Senior

Stabilny callback

Napisz hook useStableCallback(callback). Zwraca funkcję, która pozostaje ta sama przy wszystkich renderach, ale przy wywołaniu zawsze wykonuje najnowszą wersję callback - z aktualnymi propsami i stanem - i zwraca jej wynik.

Taką funkcję można włożyć do zależności efektu albo przekazać do komponentu memo bez restartowania efektu i psucia memoizacji.

Testy (4)

  1. const { result, rerender } = renderHook(({ n }) => useStableCallback(() => n), { initialProps: { n: 1 } });
    const first = result.current;
    rerender({ n: 2 });
    rerender({ n: 3 });
    expect(result.current).toBe(first);
  2. const { result, rerender } = renderHook(({ n }) => useStableCallback(() => n), { initialProps: { n: 1 } });
    expect(result.current()).toBe(1);
    rerender({ n: 2 });
    expect(result.current()).toBe(2);
  3. const { result } = renderHook(() => useStableCallback((a, b) => a + b));
    expect(result.current(2, 3)).toBe(5);
  4. const seen = [];
    function Child({ onSave }) {
      useEffect(() => {
        seen.push('effect');
      }, [onSave]);
      return null;
    }
    function Parent({ value }) {
      const onSave = useStableCallback(() => value);
      return <Child onSave={onSave} />;
    }
    const { rerender } = render(<Parent value="a" />);
    rerender(<Parent value="b" />);
    rerender(<Parent value="c" />);
    expect(seen).toEqual(['effect']);