Ensure async features that depend on a query/promise’s lifecycle (e.g., cancellation hooks, query function availability) are wired using a deterministic initialization order. Don’t write code paths that assume query/query.promise already exists; either (a) centralize initialization (e.g., reuse a prefetch-like path) or (b) explicitly create/transition query state before starting concurrent work. This prevents unreachable cancellation handles and race conditions where different callers observe different lifecycle states.
Example pattern (conceptual):
async function ensureQueryInitialized({ queryHash, queryFn, client, variables }) {
let query = client.queries.find(d => d.queryHash === queryHash)
if (!query) {
// Create/initialize via the single shared initialization path
query = await client.prefetchQuery({ queryHash, queryFn, variables })
}
return query
}
function wireCancelAtCreation({ query, pageVariables }) {
// Wire cancel when promises are created (when the handle is available)
const promises = pageVariables.map(v => {
const p = query.queryFn(v)
// store cancel handle immediately in a dedicated field
query._cancel = p.cancel
return p
})
return Promise.all(promises)
}
Standard checklist:
query and query.promise (e.g., uninitialized → initialized → running).setQueryData) that might run before initialization must either (1) wait for a shared initialization path or (2) create the query using the same logic as other entry points.Enter the URL of a public GitHub repository