Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with React 16.13: Cannot update a component [ X] while rendering a different component [Y]. #1124

Closed
ifmael opened this issue May 25, 2020 · 33 comments

Comments

@ifmael
Copy link

ifmael commented May 25, 2020

🐛 Bug Report

React show a warning when a function component is updated during another component's render phase. https://fb.me/setstate-in-render

To Reproduce

The codesandbox to reproduce the issue:

  • Open console.
  • Click on "en"

Expected behavior

I don't expect to see a warning in the console

Your Environment

  • runtime version: 12.12
  • i18next version: >= 11.5.0
  • os: Windows 10
@jamuhl
Copy link
Member

jamuhl commented May 25, 2020

Looks like more related to your sample than to what react-i18next provides?

@ifmael
Copy link
Author

ifmael commented May 25, 2020

If I remove const { t } = useTranslation(); from my components and use normal string , it doesn't happen.
In this message facebook/react#18178 (comment) , gaeron shows how to identify the source of the issue.

i18n-issue

In my component locale-provier.js, I only change the locale based on the page context

import React from 'react'
import LocaleContext from './locale-context'
import { useTranslation } from "react-i18next"

const LocaleProvider = ({ children, locale}) =>{
  const { i18n } = useTranslation()

  i18n.language !== locale && i18n.changeLanguage(locale);

  return <LocaleContext.Provider value={locale}>{ children }</LocaleContext.Provider>
}

export default LocaleProvider

@jamuhl
Copy link
Member

jamuhl commented May 25, 2020

Still, the problem does not exist in our samples...so it's specific to your setup, configuration...

@ifmael
Copy link
Author

ifmael commented May 25, 2020

Ok. How can i identify where is the problem? Because I don't have idea what is it going on

@jamuhl
Copy link
Member

jamuhl commented May 25, 2020

try:

  • adding a lng on init or using a language detector (at least in the sandbox you get a warning for that)
  • set saveMissing: false on init (that might trigger a rerender - saveMissing should not be used in production anyway)
  • try playing with useSuspense: false in react-i18next options: https://react.i18next.com/latest/i18next-instance

@chopfitzroy
Copy link

@ifmael any luck? I am seeing this to, is to do with isMounted being changed in the useTranslation hook during a render.

@jamuhl
Copy link
Member

jamuhl commented May 29, 2020

@CrashyBang isMounted is set based on useRef -> https://github.com/i18next/react-i18next/blob/master/src/useTranslation.js#L44 so no setState no rerender

Can you provide a reproducible sample on codesandbox - really would love to get this solved.

@ifmael
Copy link
Author

ifmael commented May 30, 2020

@jamuhl I've tried everything that you told me but I get the same error. The error only shows the first time that I changed the language. All subsequent navigations work correctly

@jamuhl
Copy link
Member

jamuhl commented May 30, 2020

Can't reproduce it on a non-gatsby sample - and won't invest hours to debug through the provided sample.

@ifmael
Copy link
Author

ifmael commented May 30, 2020

Finally, I've solved my issue, but to be honest, I'm not pretty sure why the below code solves the problem:

import React, { useEffect } from 'react'
import LocaleContext from './locale-context'
import { useTranslation } from "react-i18next"

const LocaleProvider = ({ children, locale}) =>{
  const { i18n } = useTranslation()

  useEffect( () =>{
    i18n.language !== locale && i18n.changeLanguage(locale);
  }, [locale]);

  return <LocaleContext.Provider value={locale}>{ children }</LocaleContext.Provider>
}

export default LocaleProvider

It's like changeLanguage method had some side-effect (probably changes the shared context), is it?

@jamuhl
Copy link
Member

jamuhl commented May 30, 2020

changeLanguage has no side-effects (it's not even react-i18next) -> it sets language on the i18next instance and sends an event that is used in useTranslation to trigger a rerender

I'm not even sure why you need a LocaleProvider...but anyway...if it works...it works

@ifmael
Copy link
Author

ifmael commented May 30, 2020

Maybe I don't need it...it's the first time I'm working with i18n and language so I am a little confused.
I'm building a blog site with gatsby + sanity.io. Also, there are several pages that I generate from static fille inside gatsby (I'm only using sanity to write the post) like index, contact, about me. From each file, I generate 2 pages (one for Spanish and another for English) with different slug and pass it a specific locale for each one.

With this locale, I feed the LocaleProvider Component in order to get in its children component the current locale for the website. Probably, there is a better approach to do that.

@jamuhl
Copy link
Member

jamuhl commented May 30, 2020

All useTranslation, withTranslation also give you the i18n instance -> i18n.language and you have the current language

@ifmael
Copy link
Author

ifmael commented May 31, 2020

Nice!. Thanks!

@an-parubets
Copy link

For my same case of problem, i was resolved it using useSuspense: false like:

const { t } = useTranslation('my-namespace', {
    useSuspense: false,
});

Thank!

@rmedaer
Copy link
Contributor

rmedaer commented Aug 25, 2020

I got the same issue while doing some test with react@experimental.

I fixed the issue by removing the line 88 of src/useTranslation.js:

if (isMounted.current) setT(getT());

If I well understand the flow, it's not mandatory. Indeed (with useSuspense: true), when the namespace is loaded, it will resolve the promise and react will go through useTranslation function again. Then the hasLoadedNamespace will be true and everything will be ready.

Btw I maybe probably missed something. I'm not familiar with react-i18next code.

@jamuhl
Copy link
Member

jamuhl commented Aug 25, 2020

@rmedaer might indeed not be needed...honestly, I never tested if it works without that line...as of the time of writing that code Suspense was still rather new.

If you like you can provide a PR removing that line...

rmedaer added a commit to rmedaer/react-i18next that referenced this issue Aug 26, 2020
As documented in i18next#1124 (comment)
this fix should avoid `setState` while react is rendering.
@rmedaer
Copy link
Contributor

rmedaer commented Aug 27, 2020

Hi there,

You probably saw the fix and PR I did yesterday. I double checked and I can confirm it fix my issues (same setState-in-render error).

Could you test the release 11.7.2 and confirm it works as well on your side ? @ifmael @an-parubets

Kind regards,

@re-thc
Copy link

re-thc commented Aug 27, 2020

This change breaks with an error t is not a function

@rmedaer
Copy link
Contributor

rmedaer commented Aug 27, 2020

@hc-codersatlas could you give us a minimal piece of code which reproduce the issue.
Currently the tests are passing. If there is indeed an issue, it will help us to debug and we will be able to add a new test in the suite.

@jamuhl
Copy link
Member

jamuhl commented Aug 27, 2020

@hc-codersatlas any update on this...not sure how getting a t is not a function is possible at all...so a codesandbox for reproduction would be awesome  🙏

@re-thc
Copy link

re-thc commented Aug 27, 2020

Bumped the version number from 11.7.1 to 11.7.2 and it came up. Haven't been able to replicate it as a separate project yet.

@jamuhl
Copy link
Member

jamuhl commented Sep 11, 2020

should be closed by #1165

@jamuhl jamuhl closed this as completed Sep 11, 2020
@trumbitta
Copy link

Even with v11.7.2, still had to set useSuspense to false to get rid of the warning. But I don't really want to handle the issues mentioned in https://react.i18next.com/latest/usetranslation-hook#not-using-suspense

I'm not sure what my next steps should be...

@jamuhl
Copy link
Member

jamuhl commented Sep 22, 2020

@trumbitta a codesandbox with reproduction case might be a good first step

@trumbitta
Copy link

@jamuhl my stacktrace lead to code similar to the one #1165 addresses, but in a different part of the file:

    function boundReset() {
      if (isMounted.current) setT(getT());
    }

@jamuhl
Copy link
Member

jamuhl commented Sep 22, 2020

still...this not yet happened ever to me...so how should I fix something that is not reproducible...

@trumbitta
Copy link

@jamuhl I hear you, and I will do my best to come back with a reproduction... meanwhile, going further with my investigations, if I disable the localStorage backend then the warning goes away.

Still not a feasible solution for my case, but at least I have one more clue for what to look for while I try to put a reproduction together.

@cichelero
Copy link

I'm also experiencing the same issue, with stacktrace also pointing to boundReset.

@trumbitta
Copy link

Update: I wasn't able to reproduce on codesandbox, but my tests on my own project all point to the localstorage backend. I fixed my issue by disabling suspense support and calling it a day.

@logemann
Copy link

logemann commented Jan 15, 2021

same for me. Playing around with suspense: false didnt change anything unfortunately. Understanding the code near the boundReset() is clearly not a no-brainer ;-)

And when i see that the nextjs guys also hitting the problem with their impl, i think there is something there. They reported that using useTranslation() might be an issue but i use it all over the place and not i18n.t(). Since this is only a development mode issue with gatsby and not in the generated pages on prod, i dont know how much time i will give this topic.

@stevenfukase
Copy link

I still have this issue on Next.js 13

@filso
Copy link

filso commented Feb 28, 2025

I also still have this issue, Next.js 14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests