← All tasksReact · Senior
Stable callback
Write a useStableCallback(callback) hook. It returns a function that stays the same across all renders but, when called, always runs the latest version of callback - with current props and state - and returns its result.
Such a function can go into effect dependencies or be passed to a memo component without restarting the effect or breaking memoization.
Ctrl+Enter runs the tests. Tab indents; to leave the editor with the keyboard, press Esc and then Tab. Your code is saved in this browser.
Tests (4)
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);
const { result, rerender } = renderHook(({ n }) => useStableCallback(() => n), { initialProps: { n: 1 } }); expect(result.current()).toBe(1); rerender({ n: 2 }); expect(result.current()).toBe(2);
const { result } = renderHook(() => useStableCallback((a, b) => a + b)); expect(result.current(2, 3)).toBe(5);
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']);