T
TanStack•4w ago
foreign-sapphire

`loader` runs on every transition despite `loaderDeps` usage

Hey all 👋 Can someone help clarify how the loader in TanStack Router works? From what I’ve observed, it seems to run on every successful route transition — even when only a minor search param changes. I tried using loaderDeps, which I assumed would act as the dependency list for when the loader should re-run, but it still re-executes on every change. I know I can use shouldReload to prevent reloading, but the function doesn’t expose the previous search parameters — which makes it hard to compare and control re-runs precisely. Has anyone run into this same behavior or found a clean workaround? Version: "@tanstack/react-router": "1.120.20" Router def:
function stripNullish<T extends Record<string, unknown>>(search: T): T {
return Object.fromEntries(
Object.entries(search).filter(
([, value]) => !isNil(value) && value !== '' && (!Array.isArray(value) || value.length > 0),
),
) as T;
}

const customSearchSerializer: SearchSerializer = searchObj => {
const strippedSearch = stripNullish(searchObj);

return defaultStringifySearch(strippedSearch);
};

export const createAppRouter = () =>
createRouter({
routeTree,
context: { theme: lightV2Theme },
defaultPreload: 'intent',
scrollRestoration: true,
defaultStructuralSharing: true,
defaultPreloadStaleTime: 0,
defaultPendingMs: 100,
basepath: '/360',
defaultPendingComponent: () => <Spinner fullscreen />,
stringifySearch: customSearchSerializer,
});
function stripNullish<T extends Record<string, unknown>>(search: T): T {
return Object.fromEntries(
Object.entries(search).filter(
([, value]) => !isNil(value) && value !== '' && (!Array.isArray(value) || value.length > 0),
),
) as T;
}

const customSearchSerializer: SearchSerializer = searchObj => {
const strippedSearch = stripNullish(searchObj);

return defaultStringifySearch(strippedSearch);
};

export const createAppRouter = () =>
createRouter({
routeTree,
context: { theme: lightV2Theme },
defaultPreload: 'intent',
scrollRestoration: true,
defaultStructuralSharing: true,
defaultPreloadStaleTime: 0,
defaultPendingMs: 100,
basepath: '/360',
defaultPendingComponent: () => <Spinner fullscreen />,
stringifySearch: customSearchSerializer,
});
2 Replies
rare-sapphire
rare-sapphire•4w ago
are you able to share more details or a minimal example? Im not seeing any loaders here
like-gold
like-gold•4w ago
stale time is 0 by default which causes to reload always

Did you find this page helpful?