Rules Hub

Coding Rules Library

← Back to all rules
fullstack ruleStack: general
hmrsingletoncachingdeveloper-experienceconfiguration

Invalidate HMR singletons on config change

Include configuration data in singleton cache keys to ensure instances are recreated when settings change during Hot Module Replacement.

PR: Feat/FCK-2245 - Cache Bellsheep and profile loaders with TanStack Query #343Created: Dec 10, 2025

Bad example

Old codets
1import { remember } from '@epic-web/remember';
2import { QueryClient } from '@tanstack/react-query';
3
4const config = {
5 defaultOptions: { queries: { staleTime: 5000 } },
6};
7
8// BAD: Key is static. Changing 'staleTime' won't update the client during HMR.
9export const queryClient = remember('query-client', () => {
10 return new QueryClient(config);
11});

Explanation (EN)

Using a static key for a persisted singleton means the instance survives HMR even if you change its configuration code. If you modify `staleTime`, the old client (with the old time) is still returned, confusing the developer.

Objašnjenje (HR)

Korištenje statičnog ključa za perzistirani singleton znači da instanca preživljava HMR čak i ako promijenite konfiguracijski kod. Ako promijenite `staleTime`, vraća se stari klijent (sa starim vremenom), što zbunjuje developera.

Good example

New codets
1import { remember } from '@epic-web/remember';
2import { QueryClient, type QueryClientConfig } from '@tanstack/react-query';
3
4const config: QueryClientConfig = {
5 defaultOptions: { queries: { staleTime: 5000 } },
6};
7
8// GOOD: Key includes config hash. Changing config invalidates the cache.
9export const queryClient = remember(
10 `query-client-${JSON.stringify(config)}`,
11 () => new QueryClient(config)
12);

Explanation (EN)

By interpolating the configuration into the cache key, any change to the config object generates a new key. This forces `remember` to discard the old instance and create a new one with the updated settings immediately.

Objašnjenje (HR)

Interpolacijom konfiguracije u ključ predmemorije, svaka promjena u konfiguracijskom objektu generira novi ključ. To prisiljava `remember` da odbaci staru instancu i odmah stvori novu s ažuriranim postavkama.

Notes (EN)

Also prefer using exported interfaces like `QueryClientConfig` over complex utility types like `ConstructorParameters<typeof QueryClient>[0]` for better readability.

Bilješke (HR)

Također preferirajte korištenje izvezenih sučelja poput `QueryClientConfig` umjesto složenih pomoćnih tipova poput `ConstructorParameters<typeof QueryClient>[0]` radi bolje čitljivosti.