-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Check existing issues
- I checked there isn't already an issue for the bug I encountered.
Describe the bug
The current implementation of useReadContracts causes unnecessary query resets when switching chains.
Current Code
export function useReadContracts<
const contracts extends readonly unknown[],
allowFailure extends boolean = true,
config extends Config = ResolvedRegister['config'],
selectData = ReadContractsData<contracts, allowFailure>,
>(
parameters: UseReadContractsParameters<
contracts,
allowFailure,
config,
selectData
> = {},
): UseReadContractsReturnType<contracts, allowFailure, selectData> {
const { contracts = [], query = {} } = parameters
const config = useConfig(parameters)
const chainId = useChainId({ config })
const options = readContractsQueryOptions<config, contracts, allowFailure>(
config,
{ ...parameters, chainId },
)
const enabled = useMemo(() => {
let isContractsValid = false
for (const contract of contracts) {
const { abi, address, functionName } =
contract as ContractFunctionParameters
if (!abi || !address || !functionName) {
isContractsValid = false
break
}
isContractsValid = true
}
return Boolean(isContractsValid && (query.enabled ?? true))
}, [contracts, query.enabled])
return useQuery({
...options,
...query,
enabled,
structuralSharing: query.structuralSharing ?? structuralSharing,
})
}Note in particular:
const options = readContractsQueryOptions<config, contracts, allowFailure>(
config,
{ ...parameters, chainId },
)Problem
Including chainId in the query key means that switching chains always resets the query, even when the contracts themselves specify a chainId.
This is problematic in cases like the following:
const query = useReadContracts({
contracts: [
{
address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC
chainId: base.id,
args: [account.address!],
abi: erc20Abi,
functionName: 'balanceOf',
},
{
address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E', // USDC
chainId: avalanche.id,
args: [account.address!],
abi: erc20Abi,
functionName: 'balanceOf',
},
],
});Here, the contracts themselves define which chainId to use, so relying on the "current chain" is unnecessary and causes extra invalidations.
Suggested Solution
Before falling back to the current chainId, check whether the contracts already define their own chainId.
This would prevent queries from being reset incorrectly when the user switches networks, while still preserving the existing behavior for cases where chainId is not explicitly provided in the contracts.
Link to Minimal Reproducible Example
https://stackblitz.com/edit/new-wagmi-utpexcpt?file=src%2FApp.tsx
Steps To Reproduce
Problem only happens on the first load of each query (before it gets cached by react-query):
- load page and wait on contract read fetch to complete
- switch to base/avalanche
- see that data is refetched
This is unwanted, because those contracts reads are unrelated to the current chain id.
What Wagmi package(s) are you using?
wagmi
Wagmi Package(s) Version(s)
latest
Viem Version
latest
TypeScript Version
latest
Anything else?
No response