I am trying to use useQuery for smart contract interaction.
The problem is, the contract
return from useContract
is null initially, as library
and chainId
are null initially.
So, the first fetch from useQuery
is using a null contract
to call the fetchPaginated
function. Even library
and chainId
got initialised such that contract
is not null, the useQuery
does not get refetched.
The contract
is a complex object that can't be set as query keys.
How to trigger the refetch for this kind of dynamic query function in useQuery
?
Below are the codes:
// hook for handling contract
export function useContract<T extends Contract = Contract>(
address: string,
ABI: any,
withSignerIfPossible = true,
): T | null {
const { library, account, chainId } = useWeb3React();
return useMemo(() => {
if (!address || !ABI || !library || !chainId) return null;
try {
return getContract(
address,
ABI,
library,
withSignerIfPossible && account ? account : undefined,
);
} catch (error) {
console.error('Failed to get contract', error);
return null;
}
}, [address, ABI, library, chainId, withSignerIfPossible, account]) as T;
}
// The useQuery that want to get refetched
export const useFetchERC20Contracts = (
page: number,
pageSize: number,
) => {
const contract = useContract();
const result = useQuery<Response>(
['contract', page, pageSize],
async () => {
if (!contract) {
return [];
}
return contract.fetchPaginated(page, pageSize);
},
{ cacheTime: 0 },
);
return result;
};
everything that the queryFn depends on and that should drive the query to re-fetch should go into the query key. If you can't put contract
there for some reason, you have to add its dependencies, in this case:
address, ABI, library, chainId, withSignerIfPossible, account
generally, I wouldn't separate this into two hooks. I would just have the queryFn call getContract
directly, because that makes the dependencies obvious.