You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 02:40:37