我有一个依赖项 windowSize。我还有一个搜索输入字段,用于更新搜索状态。如果我在搜索状态中提示某些内容,我的网站当然会重新渲染,因为我更新了状态。但我有一个包含在 useCallback 中的函数,但问题是,它会被触发。那么为什么它会被触发?它应该只在依赖项/状态 windowSize 发生变化时触发。
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])
const columnCount = numColumns ?? calculateColumnCount(containerWidth);
我只把重要的内容放在了代码片段中。如果你需要,我可以分享完整的代码。
我做错了什么?
您的功能被触发是因为:
当您执行 useCallback 时,它会创建一个函数,用于获取
recreated
useCallback 依赖项是否发生变化的信息。在组件主体中指定此类信息时,columnCount
每次重新渲染时都会调用该函数。如果您想阻止呼叫,您必须使用Memo:
要记住的一件事是, 钩子
useCallback
不会阻止调用,它确保只要函数依赖项(windowSize
在您的情况下)不变,函数引用在渲染过程中保持稳定。这行
只要为假,就会执行
numColumns
。此执行与引用是否发生改变无关useCallback
。要记住的第二点是
状态更改会导致重新渲染。当您
searchValue
通过在搜索输入字段中键入内容来更新状态时,它会导致组件重新渲染。在重新渲染期间,如果numColumns
为假,calculateColumnCount
则再次调用该函数。https://react.dev/learn/updating-objects-in-state
因此,如果您的目的只是调用一次函数,请使用
useEffect
具有空依赖数组的函数(即使编译器引发小警告也没关系)。如果此解决方案不能让您满意,您还可以使用
useMemo
钩子或者考虑使用 react redux 工具包,它将帮助你有效地管理状态。它的学习曲线可能很难,但我真心推荐 :)
继续编码吧兄弟,玩得开心:)