关于useCallback依赖与pollBalance函数触发逻辑的技术疑问
关于useCallback与状态更新的逻辑疑问
以下是相关代码:
const [balance, setBalance] = useState(); const pollBalance = useCallback(async (provider, address) => { if (provider && address) { const newBalance = await provider.getBalance(address); if (!newBalance.eq(balance !== null && balance !== void 0 ? balance : zero)) { setBalance(newBalance); console.log(address, newBalance.toString(), balance); } } }, [balance]);
我的疑问:
我对useCallback Hook的理解是:pollBalance函数仅会在balance状态变化时重新创建,否则会复用之前的函数实例。但我在该函数内部通过setBalance(newBalance)修改了balance状态,那么从技术层面来说,是不是balance永远不会发生变化,导致pollBalance永远不会被重新创建?
解答:
首先纠正一个理解偏差:useCallback的核心是缓存函数实例,只有当依赖项(此处为balance)变化时,才会生成新的函数实例——它并不控制函数的调用时机,只决定是否生成新实例。
回到你的代码逻辑,实际流程是这样的:
- 初始渲染时,
balance为undefined,此时创建第一个pollBalance实例,它捕获的balance值是undefined。 - 当
pollBalance被触发调用(比如通过定时器、用户事件等),如果获取到的newBalance和当前捕获的balance不相等,就会执行setBalance(newBalance)更新状态。 balance更新后,组件会重新渲染,此时useCallback的依赖项balance发生变化,会生成新的pollBalance函数实例,这个新实例捕获的是更新后的balance值。- 后续如果再次调用这个新的
pollBalance实例,它会用最新的balance和newBalance对比,有差异就再次更新状态,循环往复。
所以你的担忧不成立:balance会正常更新,每次更新都会触发生成新的pollBalance实例。不过这里有个潜在问题:如果pollBalance是被重复调用的(比如定时轮询),旧的函数实例可能还持有之前的balance闭包值,可能导致不必要的状态更新。解决这个问题的话,可以改用函数式更新setBalance(prev => newBalance),或者把balance从useCallback的依赖中移除,改用ref来跟踪最新值,避免频繁生成新的函数实例。
内容的提问来源于stack exchange,提问作者TECH HINDER
相关产品推荐
相关产品推荐

