Active Cache & Config Safety

When implementing caching layers/providers and cache-driven handlers: - **Assume multiple cache instances may exist.** Avoid single “default cache” globals for runtime behaviors (e.g., focus handlers). Track **all active caches** and update/notify each.

copy reviewer prompt

Prompt

Reviewer Prompt

When implementing caching layers/providers and cache-driven handlers:

  • Assume multiple cache instances may exist. Avoid single “default cache” globals for runtime behaviors (e.g., focus handlers). Track all active caches and update/notify each.
  • Create cache instances exactly once. If a cache prop isn’t provided, ensure the provider creates a single cache instance (not a new one per render).
  • Define cleanup semantics for created vs injected caches. If the provider created a cache, clean it up on unmount and when it’s replaced; if a cache was injected by the parent, do not dispose it inside the provider.
  • Never mutate shared config objects stored in cached entries. When applying per-query/per-hook config, avoid mutating a config object referenced by another query instance. Prefer replacing with a new merged object.

Example: safe config merge (avoid mutating a shared reference)

// BAD: mutates shared object reference
// Object.assign(query.config, config)

// GOOD: replace with a new merged object
query.config = { ...query.config, ...config }

Example: multi-cache handling pattern (conceptual)

// Instead of using a single default cache ref for focus events,
// maintain a registry/list of active caches and notify all.
activeCaches.forEach((cache) => {
  if (/* visible + online */) {
    cache.refetchAllOnWindowFocus?.()
  }
})

These rules prevent hard-to-debug cross-query/cross-cache state leaks and make behavior correct under multi-cache usage.

Source discussions