next-translate
next-translate copied to clipboard
Dont`t consume NextJs useRouter hook in I18nProvider
The current implementation of NextJs useRouter hook returns the entire context object as a consumer.
export function useRouter(): NextRouter {
return React.useContext(RouterContext)
}
Part of the context is the property asPath which includes the query and hash shown in the browser. For in-page navigation purposes, e.g., using a table of content, the hash gets used to navigate to the respective page sections.
Changing minor navigation aspects like the should not result in a change of asPath, but in NextJs it results in a different context. Based on the useRouter implementation, a re-rendering occurs.
Using the NextJs useRouter hook in I18nProvider, the consequence is that the Provider re-creates itself anytime a minor in-page navigation gets triggered.
To avoid this, provide the values from the Next context required within I18nProvider from the outside like that.
Memo in _app
const { __namespaces, __lang } = pageProps;
const {
query: { slug },
locale,
defaultLocale,
} = useRouter();
const component = useMemo(() => {
return (
<I18nProvider
lang={__lang}
namespaces={__namespaces}
// provide relevant properties from the outside
// tested locally and it seems those are not required, even when removing useRouter from I18nProvider
locale={locale}
defaultLocale={defaultLocale}
>
<Component {...pageProps} />
</I18nProvider>
);
}, [slug, locale]); // re-create the component instance when slug or locale changes
The above example relies on loading relevant namespaces in getStaticProps, here for dynamic pages, which works really good.
export const getStaticProps: GetStaticProps<Props> = async (ctx) => {
const { params: { slug } = { slug: [] }, locale } = ctx;
const pathname = path.sep.concat(
Array.isArray(slug) ? slug.join(path.sep) : slug
);
const translation = await loadNamespaces({
...i18nConfig,
pathname,
locale
});
return {
props: {
...translation
}
};
};
Can you please elaborate a constellation where properties of useRouter are actually relevant in I18nProvider? I have removed the hook and those properties entirely from I18nProvider and it still works perfectly.
Thx!
Feel free to PR @gurkerl83 ! Thanks for your proposal!
Not sure if the same but with nextjs 13.5 i am getting the same (and strangely only with NODE_ENV=test):
Error: NextRouter was not mounted. https://nextjs.org/docs/messages/next-router-not-mounted at useRouter (C:\app\client\node_modules\next\dist\client\router.js:146:15) at I18nProvider (C:\app\client\node_modules\next-translate\lib\cjs\I18nProvider.js:50:37)
downgrading to nextjs 13.4.19 solves it
@gittygoo I am facing the same problem
I get the same issue with next 14 with or without NODE_ENV=test