为何useCallback未阻止闭包函数随组件渲染重生成?
问题原因分析与解决方案
为什么你的代码达不到预期?
- 你对
useCallback的用法理解有偏差:useCallback的核心作用是缓存传入的函数本身的引用,但你当前的写法是useCallback(() => { ... }, [])()—— 这里useCallback确实缓存了外层匿名函数的引用,但后面的()会在每次组件渲染时都执行这个缓存的函数。而这个函数每次执行都会重新创建counter变量和updateCounter函数,最终赋值给reverseGrid的是每次执行生成的新函数,自然会在每次渲染时重新生成。 - 另外,
counter定义在这个立即执行函数的作用域内,每次执行函数都会把counter重新初始化为3,根本做不到持久化存储。
正确的实现方式
要实现「私有持久化的counter + 缓存函数引用」的效果,应该用useRef存储持久化的counter值,再用useCallback直接包裹目标操作函数:
const counterRef = useRef(3); const reverseGrid = useCallback(({ type }) => { switch (type) { case "INCREMENT": counterRef.current = counterRef.current === refPreviousGrid.current.length ? refPreviousGrid.current.length : counterRef.current + 1; return counterRef.current; case "DECREMENT": counterRef.current = counterRef.current === 0 ? 0 : counterRef.current - 1; return counterRef.current; case "RESET": counterRef.current = 3; break; } }, [refPreviousGrid]);
为什么这样可行?
useRef的.current属性会在组件整个生命周期中保持引用不变,不会随组件渲染重置,完美替代你想通过闭包持久化的counter变量。useCallback直接包裹reverseGrid对应的函数,只要依赖项数组[refPreviousGrid]里的内容不变,这个函数的引用就会被缓存,不会每次渲染都重新生成。
内容的提问来源于stack exchange,提问作者NicolaL1995
相关产品推荐
相关产品推荐

