为何useCallback在依赖windowSize未更新时仍触发?
问题原因与解决方案
核心误解
你对useCallback的作用理解有误:useCallback的本质是缓存函数的引用,保证只有当依赖项变化时,才会生成新的函数实例。但它并不会限制函数的调用时机——只要代码里执行了这个函数(比如你这里的calculateColumnCount(containerWidth)),不管依赖有没有变,函数都会被触发执行。
你的代码问题
当searchValue变化时,组件重新渲染,此时代码会执行const columnCount = numColumns ?? calculateColumnCount(containerWidth),这里直接调用了calculateColumnCount函数,所以console.log('CALLBACK FUNC')会触发,和useCallback的依赖无关。
解决方案
如果你想让calculateColumnCount的执行结果只在windowSize(或相关依赖)变化时才重新计算,需要用useMemo来缓存计算结果,而不是只缓存函数引用:
const [searchValue, setSearchValue] = useState<string>(''); useEffect(() => { gridRef.current?.recomputeGridSize(); console.log('TRIGGER WINDOW SIZE') }, [windowSize]); const calculateColumnCount = useCallback((width: number) => { console.log('CALLBACK FUNC') return Math.floor(width / itemMinWidth); }, [windowSize, itemMinWidth]) // 注意:如果itemMinWidth是外部变量/状态,必须加入依赖 // 用useMemo缓存计算结果,只有依赖变化时才重新调用函数 const columnCount = useMemo(() => { return numColumns ?? calculateColumnCount(containerWidth); }, [numColumns, calculateColumnCount, containerWidth]);
这样,只有当numColumns、calculateColumnCount(即windowSize变化时)或containerWidth变化时,才会重新调用calculateColumnCount并更新columnCount,searchValue变化时不会触发函数执行。
内容的提问来源于stack exchange,提问作者wepro01
相关产品推荐
相关产品推荐

