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
相关产品推荐
相关产品推荐

