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

React Memorized Components Being Unnecessarily Re-rendered #329

Closed
mwskwong opened this issue Oct 26, 2019 · 1 comment
Closed

React Memorized Components Being Unnecessarily Re-rendered #329

mwskwong opened this issue Oct 26, 2019 · 1 comment

Comments

@mwskwong
Copy link

Describe the bug
While accessing the t function in a memorized component (either memo or PureComponent), the component is being unnecessarily re-rendered. For me, it seems that this only happens if i18next-xhr-backend is used. In the codesandbox sample, 1 extra render is fired. While the worst I have met (in rare situation) is 7 extra renders.

Occurs in react-i18next version
react-i18next@11.0.0

To Reproduce
Just use useTranslation or withTranslation in a memorized component
https://codesandbox.io/s/react-i18next-test-wzj08
https://codesandbox.io/s/react-i18next-test-z4jx0 (extended by @jamuhl)

Expected behaviour
A memorized component should behave the same as a normal component in terms of utilizing react-i18next.

Additional context
I have also posted this issue on react-i18next, since I'm not sure whether react-i18next or i18next-xhr-backend causes this.
Original discussion: i18next/react-i18next#710 (comment)

@jamuhl Please read the console output for details (and forget whether the backend locates the translation.json or not).
** ONLY causes unnecessary re-renders when using i18next-xhr-backend**

https://codesandbox.io/s/react-i18next-test-wzj08

If you believe it is easier for you guys to trace and maintain, I can open a new issue instead of continuing the discussion on this issue.

Wow...that is so weird - I extended your sample a little: https://codesandbox.io/s/react-i18next-test-z4jx0

(making sure no saveMissing, ... gets in the way, also adding a counter to the MemorizedButton to see it gets rendered to DOM only once - while called twice)

I moved the sample to local so I could add some more logs to the useTranslation:

// ...
  if (!ready && !useSuspense) return ret; // not yet loaded namespaces -> load them -> and trigger suspense

  throw new Promise(function(resolve) {
    console.warn(`${props.name} throw Promise (trigger Suspense)`);
    loadNamespaces(i18n, namespaces, function() {
      console.warn(`${props.name} set state (loaded namespace -> sets new t function)`);
      setT(getT());
      console.warn(`${props.name} resolves Promise (resume Suspense)`);
      resolve();
    });
  });

image

The SimpleButton gets triggered it's rerender by the setT. Immediately after the MemorizedButton also renders - honestly I have no idea why. Then Suspense get resolved by the SimpleButton - removing the fallbackUI and showing the real content again. Then setT gets called for the MemorizedButton - and it rerenders (calls the function internally) while the rendered result stays the memoized memorizedButton1 (counter says 2)...

Change the order of the 2 Buttons MemorizedButton before SimpleButton -> only one render as SimpleButton gives a shit about MemorizedButton gets setT called.

Move every Component in own Suspense -> both render only once

So...if this is related to react-i18next - feel free to provide a PR...as I don't know which magic triggers a rerender on the memorized component...I have no clue how to fix this...

To make it more clear - I got no idea what is triggering this render:

image

I just know it's not useTranslation (neither the loading done as it comes later nor the bound events)

@jamuhl
Copy link
Member

jamuhl commented Oct 26, 2019

Nothing todo with xhr-backend...not having one just does not trigger Suspense

@jamuhl jamuhl closed this as completed Oct 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants