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

DynamicModuleLoader's children mounts twice #66

Closed
anilanar opened this issue Mar 7, 2019 · 16 comments
Closed

DynamicModuleLoader's children mounts twice #66

anilanar opened this issue Mar 7, 2019 · 16 comments
Assignees

Comments

@anilanar
Copy link
Contributor

anilanar commented Mar 7, 2019

Due to the following workaround:

https://github.com/Microsoft/redux-dynamic-modules/blob/e1046942f26db108f7dbb6ccc593824c9de716f5/packages/redux-dynamic-modules/src/DynamicModuleLoader.tsx#L142-L147

children of DynamicModuleLoader is mounted twice, once with a <Provider> wrapper and once without the wrapper.

I think this workaround is not needed anymore since React 16.6.3 and store.getState() gives the correct state on first render.

Nevermind, it still behaves the same. I forked and unconditionally wrapped the component with the Provider always, which is better than double mounting IMO and has no side effects AFAIK.

@navneet-g
Copy link
Contributor

@anilanar thanks for reporting, Can you give a codesandbox with repro?

@anilanar
Copy link
Contributor Author

anilanar commented Mar 7, 2019

https://codesandbox.io/s/8kx2jr7762

This behaviour is expected. If you do the following, Comp will mount twice because React re-creates the whole element tree if the root's type is different than before.

let count = 0;
const App = () => (
  if (count++) return <div><Comp /></div>;
  else return <Comp />;
);

@navneet-g
Copy link
Contributor

Sorry I didn't get a chance to look at it yet. I will take a look this week and get back to you.

@navneet-g
Copy link
Contributor

@anilanar I am not able to open the sandbox, I get following error. I will try again later today
image

@navneet-g navneet-g self-assigned this Mar 14, 2019
@anilanar
Copy link
Contributor Author

Perhaps codesandbox had problems when you tried it, I can open it.

@navneet-g
Copy link
Contributor

I can repro this and this is what I see, the storeState changes and thus React rerenders children
We need to debug more to see why the storeState is not upto date in first render after the module is loaded. Most probabbly this is another side effect of React's new context API, but for sure this is not a bug in redux-dynamic-modules. It takes a long time to debug react, I will give it a try later in the week if I get sometime.

image

@shockk
Copy link

shockk commented Mar 20, 2019

I have this trouble too. This issue blocks releasing our app (

@anilanar
Copy link
Contributor Author

anilanar commented Mar 20, 2019

@navneet-g State not being up to date after store is updated (by redux-dynamic-modules) is not a bug in redux-dynamic-modules. But using two different component roots (to overcome aforementioned problem) is a bug in redux-dynamic-modules.

@navneet-g
Copy link
Contributor

@shockk in our app we are using following version of react-redux, and redux and don't see this issue. We are using it with React 16.8. Please try these versions for now to unblock the release.
react-redux": "^5.1.1",
"redux": "^4.0.0",

@navneet-g
Copy link
Contributor

@anilanar which two different component roots are you mentioning? Please elaborate.

@anilanar
Copy link
Contributor Author

anilanar commented Mar 20, 2019

@navneet-g

First the following:

https://github.com/Microsoft/redux-dynamic-modules/blob/master/packages/redux-dynamic-modules/src/DynamicModuleLoader.tsx#L135-L148

and

https://github.com/Microsoft/redux-dynamic-modules/blob/master/packages/redux-dynamic-modules/src/DynamicModuleLoader.tsx#L116-L125

_getLatestState will be true on the first render and will be false on the second render. Thus, on the first render, it will render something like:

<ReactReduxContext.Provider ...>
  {children}
</ReactReduxContext.Provider>

On the second render, it will just render the {children}. Because the root of the component changes from ReactReduxContext.Provider to children's root component, whatever is inside {children} will mount twice no matter what.

In my fork, I removed _getLatestState and unconditionally call _renderWithReactReduxContext which works for the first render and also for subsequent renders without a problem.

@navneet-g
Copy link
Contributor

Thanks @anilanar ... @abettadapur can you take a look?

@abettadapur
Copy link
Collaborator

@anilanar @shockk Sorry for the delay here. Could you guys try this version of the package and let me know if you still have issues?

redux-dynamic-modules@3.5.0-alpha.3

@anilanar
Copy link
Contributor Author

anilanar commented Mar 25, 2019

@abettadapur It works. To understand the effects of strictMode, I created the following sandbox with bunch of console.logs, checking state update order of connected components inside and outside DynamicModuleLoader and also assigning refs to DynamicModuleLoader's children from outside.

https://codesandbox.io/s/73r20x4jzj

I think there's a difference only when mounting and not during updates. strictMode changes the order of state updates when mounting. When it's turned off, DynamicModuleLoaders children's connected state updates before anyone else.

@abettadapur
Copy link
Collaborator

correct, the only difference should be at mount time. I don't think we can get around this for strict consumers. Thanks for verifying and the example!

@navneet-g Let's move to publish the new version

@navneet-g
Copy link
Contributor

Thanks @anilanar and @abettadapur .
@abettadapur I left a comment on your PR, let me know you want to address before merging or in a separate PR.

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

4 participants