T
TanStack3mo ago
stormy-gold

Invalidate router inside beforeLoad

Hey, I'm using tanstack start. Is there a way to invalidate the router inside beforeLoad? I update a language cookie in beforeLoad (so it triggers on link hover and on click : also I don't know if this is the intended behaviour but when I hover a link, it triggers a first time, when I left click it triggers a second time, and when I release it triggers a third time, I was expecting it to only trigger once after hover, or at most twice after hover and click. Also, in beforeLoad, preload is always false). But when I actually click the link, despite the cookie has changed, the loader doesn't fires so the language texts are not updated.
export const Route = createRootRouteWithContext<RouterContext>()({
head: () => ({
// ...
}),
component: RootComponent,
beforeLoad: async (args) => {
if (args.preload) { // always false
return;
}
const pathname = args.location.pathname;
const language = await getLanguageFromPathname(pathname);
const cookieLanguage = await getLanguage();

if (cookieLanguage != language) {
await updateLanguage({ data: { lng: language } });
}
},
loader: async (args) => {
const pathname = args.location.pathname;
const language = await getLanguageFromPathname(pathname);

const i18n = await args.context.queryClient.ensureQueryData(
getI18nQuery(language),
);
return {
lng: language,
i18n,
};
},
});

export function RootComponent() {
return (
<RootDocument>
<Outlet />
</RootDocument>
);
}

function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
const data = Route.useLoaderData();
const { i18n, lng } = data;
console.log("LANG DATA", i18n);

return (
<html lang={lng} className={""}>
<head>
<HeadContent />
</head>
<body
>
<IntlProvider {...i18n}>
{children}
</IntlProvider>
</body>
</html>
);
}
export const Route = createRootRouteWithContext<RouterContext>()({
head: () => ({
// ...
}),
component: RootComponent,
beforeLoad: async (args) => {
if (args.preload) { // always false
return;
}
const pathname = args.location.pathname;
const language = await getLanguageFromPathname(pathname);
const cookieLanguage = await getLanguage();

if (cookieLanguage != language) {
await updateLanguage({ data: { lng: language } });
}
},
loader: async (args) => {
const pathname = args.location.pathname;
const language = await getLanguageFromPathname(pathname);

const i18n = await args.context.queryClient.ensureQueryData(
getI18nQuery(language),
);
return {
lng: language,
i18n,
};
},
});

export function RootComponent() {
return (
<RootDocument>
<Outlet />
</RootDocument>
);
}

function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
const data = Route.useLoaderData();
const { i18n, lng } = data;
console.log("LANG DATA", i18n);

return (
<html lang={lng} className={""}>
<head>
<HeadContent />
</head>
<body
>
<IntlProvider {...i18n}>
{children}
</IntlProvider>
</body>
</html>
);
}
2 Replies
stormy-gold
stormy-goldOP3mo ago
An idea was that, on beforeLoad, if we are not preloading (on hover), but we clicked a route that has a different locale than the current one, then we throw redirect. But as mentioned, preload is always false, and redirect doesn't hard refresh so the loader is not firing.
flat-fuchsia
flat-fuchsia3mo ago
looks like you should add the language as a loader dependency ?

Did you find this page helpful?