i18next/next-i18next

appWithTranslation is causing the React state to not consist when doing client-side page navigation.

pgburrack opened this issue ยท 7 comments

๐Ÿ› Bug Report

Wrapper _.app.js with the appWithTranslation HOC is causing the React state to not consist when doing client-side page navigation.

To Reproduce

I created this repo with a simple example that you can clone and try:
https://github.com/pgburrack/next-i18next-issue

In the example repo I created a DummyProvider with the initial state.

const [state, setState] = useState({
    a: null
  });

Steps to reproduce:

  1. start repo by running npm run dev + open http://localhost:3000/
  2. Open console developer tools. I would expect to see:
{a: null}
{a: null}
{a: 'foo'}
{a: 'foo'}

๐Ÿ‘† this is the state that is in the DummyProvider.
3. Click on "Go to about page" (while keeping the console open)
image

You will see that the state in DummyProiver is initiated again.

{
  a: null
}

Note: if you comment out appWithTranslation and just export the App component.
you will see that the state is being kept on client-side navigation.

Expected behavior

When navigating to the /about page i would expect the DummayProvider to be

{a: 'foo'}

Your Environment

  • runtime version: Node, v18.15.0, testing on chrome
  • i18next version: "23.7.16"
  • "next-i18next": "15.0.0"
  • "react-i18next": "13.4.1"
  • "next": "12.2.4",
  • os: Mac
  • any other relevant information

P.S i found that if I pass options to appWithTranslation it will work as expected.

Example:

export default appWithTranslation(MyApp, {
  i18n: {
    defaultLocale: DefaultLocale,
    locales: SupportedLocales,
  })

The docs are not saying to do that as well, as we have that information in next-i18next.config.js so i am not sure why i would need to do that.

I suspect that the following line of code is causing the issue

https://github.com/i18next/next-i18next/blob/master/src/appWithTranslation.tsx#L120

    return i18n !== null ? (
      <I18nextProvider i18n={i18n}>
        <WrappedComponent {...props} />
      </I18nextProvider>
    ) : (
      <WrappedComponent key={locale} {...props} />
    )

I saw that when doing the navigation will disappear.

Could use help with this ๐Ÿ™

I also noticed that the issue is only happening when one page is translated and the other is not.

I also noticed that the issue is only happening when one page is translated and the other is not.

That's exactly the problem...
if a page is not using next-i18next, there is nothing that will correctly initialize next-i18next...
So you can either use next-i18next on every page or pass the nextI18nextConfig config via appWithTranslation... (btw: you don't need to create a new "empty" config, you can just pass in the original config)

import nextI18nextConfig from '../../next-i18next.config';
//...
export default appWithTranslation(MyApp, nextI18nextConfig);

Hi @adrai

Thanks for the quick reply and the suggestion!

To give you some context on my original issue which made create this example repo and this Github issue.

I started to add next-i18next to a few page in an existing NextJs website that has a lot of pages.
I started seeing bugs which made me start investigate and find the issue with next-i18next.

I am wondering if there is a way next-i18next can always make sure to wrap an app with the <I18nextProvider i18n={i18n}> provider and either default i18n to an empty object to avoid react state from getting cleared? not sure what are the implications of that?

OR

update the README/docs to mention the issue here and how to solve it?

basically to make sure other people are not facing the same issue ๐Ÿ˜ƒ

Maybe something like:

Partially translated website

OR

Start using next-i18next Incrementally

If you want to only use next-i18next on some pages make sure to do the following

import nextI18nextConfig from '../../next-i18next.config';
//...
export default appWithTranslation(MyApp, nextI18nextConfig);

Feel free to provide a PR to update the readme

@adrai sure ๐Ÿ˜„

just confirm: you don't think it is feasible or good idea to always wrap the app with a Provider? and if no, why? ๐Ÿ™

no, we tried this in the past, and it resulted in other errors

Opened a PR
#2260