React useState问题:useCallback防抖函数中状态值始终为空
问题分析与解决方案
核心问题:闭包导致防抖函数捕获旧状态
你的防抖函数始终拿到空数组,是因为闭包特性:debounceOnChangeScript 通过 useCallback 创建,依赖项为空数组,意味着它会一直使用组件初始渲染时的 inputArr 快照(也就是空数组)。后续状态更新后,防抖函数内部的 inputArr 并不会自动更新,始终指向初始值。
另外你的 getCheckedValues 里也有小问题:setInputArr 是异步操作,调用后立刻 console.log(inputArr) 也拿不到最新状态,因为当前渲染周期的 inputArr 还没更新。
代码修正步骤
1. 优化状态更新逻辑(避免依赖当前状态快照)
把直接依赖 inputArr 的更新改成函数式更新,确保每次都能拿到最新的前序状态,同时用 find 替代 filter(因为你只需要匹配单个对象):
const getCheckedValues = (e) => { if (e.target.checked) { const targetId = Number(e.target.id); const targetObj = tableData.find(obj => obj.id === targetId); if (targetObj) { // 函数式更新:prev 是当前最新的 inputArr 状态 setInputArr(prev => [...prev, { id: targetObj.id, schemaName: targetObj.schemaName, tableName: targetObj.tableName, keys: targetObj.keys }]); } } };
2. 解决防抖函数的闭包问题(两种可选方案)
方案一:调用防抖函数时传入最新状态
直接把当前最新的 inputArr 作为参数传给防抖函数,避免依赖闭包中的旧值:
// 重新定义防抖函数,接收当前状态作为参数 const debounceOnChangeScript = React.useCallback(debounce((value, id, currentInputArr) => { console.log('Inside onChangeScript'); console.log(currentInputArr); currentInputArr.forEach(element => console.log(element)); }, 1000), []); // 调用防抖函数时,传入最新的 inputArr // 示例:比如在某个触发事件中调用 // debounceOnChangeScript(someValue, someId, inputArr);
方案二:用 useRef 保存最新状态
通过 useRef 同步状态的最新值,防抖函数直接读取 ref.current 获取最新数据:
// 创建 ref 同步 inputArr 的最新值 const inputArrRef = React.useRef(inputArr); // 每次 inputArr 更新时,同步到 ref React.useEffect(() => { inputArrRef.current = inputArr; }, [inputArr]); // 防抖函数读取 ref.current 获取最新状态 const debounceOnChangeScript = React.useCallback(debounce((value, id) => { console.log('Inside onChangeScript'); console.log(inputArrRef.current); inputArrRef.current.forEach(element => console.log(element)); }, 1000), []);
内容的提问来源于stack exchange,提问作者Karthik Saxena
相关产品推荐
相关产品推荐

