核心思想
useCallback 是一个 React Hook,它用于缓存(或称‘记忆化’)一个函数。这能确保在多次重新渲染之间,只要依赖项没有改变,这个函数就不会被重新创建,从而保持其引用的稳定性。
1 2 3 4 5 6 7 8
| const memoizedCallback = useCallback(() => { }, [dependencies]);
|
为什么需要 useCallback
在 React 中,函数组件每次渲染时都会重新创建函数对象。例如:
1 2 3 4 5 6 7
| function MyComponent() { const handleClick = () => { console.log("clicked"); };
return <button onClick={handleClick}>Click</button>; }
|
这里的 handleClick 每次渲染都会是一个 新的函数对象。如果这个函数作为 props 传给子组件,那么即使逻辑不变,子组件也会认为 props 变了,从而 导致子组件重新渲染。
1 2 3 4 5 6 7
| function MyComponent() { const handleClick = useCallback(() => { console.log("clicked"); }, []);
return <button onClick={handleClick}>Click</button>; }
|
这样 handleClick 的引用在组件多次渲染时保持不变。
举例对比
❌ 不用 useCallback
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const Parent = () => { const [count, setCount] = useState(0);
const increment = () => setCount((c) => c + 1);
return ( <div> <Child onClick={increment} /> <p>{count}</p> </div> ); };
const Child = React.memo(({ onClick }) => { console.log("Child render"); return <button onClick={onClick}>Increment</button>; });
|
即使 count 变化,increment 每次都是新函数 → Child 每次都会重新渲染。
✅ 用 useCallback
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const Parent = () => { const [count, setCount] = useState(0);
const increment = useCallback(() => { setCount((c) => c + 1); }, []);
return ( <div> <Child onClick={increment} /> <p>{count}</p> </div> ); };
|
这样 Child 不会因为函数引用变化而重复渲染,只在必要时更新。