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

react-query useQuery动态查询函数如何触发自动refetch

useQuery 结合web3合约实例的重触发方案

核心思路:不需要将复杂的contract实例放入query key,只需要将决定contract实例有效性、唯一性的原始依赖项加入query key,配合enabled配置控制查询时机,即可实现自动重请求。


具体实现步骤

  • 第一步:补全useContract的传参,原代码中调用useContract()未传入必填的address、ABI参数,会导致contract永远返回null
  • 第二步:将contract依赖的可序列化原始值(合约地址、chainId、连接的account等)加入query key,这些值变更时useQuery会自动判定查询失效、重新执行
  • 第三步:添加enabled配置项,仅当contract实例存在时才执行查询函数,从根源避免null值调用合约方法的问题

修改后可直接运行的代码

export const useFetchERC20Contracts = (
  page: number,
  pageSize: number,
  contractAddress: string,
  ERC20_ABI: any
) => {
  // 从web3上下文拿到链id、账户信息,这些都是contract实例的核心依赖
  const { chainId, account } = useWeb3React();
  const contract = useContract(contractAddress, ERC20_ABI);

  const result = useQuery<Response>(
    // query key全部使用可序列化的原始值,contract变化等价于这些值变化
    ['erc20', 'paginatedList', contractAddress, chainId, account, page, pageSize],
    async () => {
      // 因为加了enabled判断,进入查询函数时contract一定非空,不需要额外判空
      return contract.fetchPaginated(page, pageSize);
    },
    {
      cacheTime: 0,
      // 仅当contract实例存在时才允许发起查询
      enabled: !!contract
    }
  );

  return result;
};

方案原理说明

  • contract实例本身是address/ABI/library/chainId/account这几个值派生出来的产物,只要这几个值不变,contract实例的功能就不会变,完全不需要把整个实例放进query key
  • enabled: !!contract会在contract为null时直接暂停查询,不会执行无效的请求逻辑;当library、chainId初始化完成,contract变为非null值时,enabled条件满足,加上query key里的chainId等依赖值已经更新,useQuery会自动触发一次新的查询

不推荐的备选方案

如果不想调整query key,也可以通过useEffect监听contract的变化,手动触发重查:

useEffect(() => {
  if (contract) {
    result.refetch()
  }
}, [contract])

这种命令式触发的方式维护成本更高,容易漏依赖,优先使用前面的声明式方案。


内容的提问来源于stack exchange,提问作者ykn121

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 03:15:48