Getting weird flashing when navigating
rubencodes opened this issue · 9 comments
I've found that when I use this to async load a component, if I navigate to a different route that uses the same component, the app briefly hits the loading component, before re-mounting the resolved component. No network request is made, since it's already been loaded, but I do get a brief flash of the loading component. Is there any way to prevent this, or is this known/expected behavior?
Hey @rubencodes this is certainly not expected behaviour.
Can you please share a bit more about your setup? i.e. version, SSR/browser etc. Also how you are creating the AsyncComponent. Thanks!
Sure! I'm on Beta 3, no SSR, using the latest Google Chrome. Also using Preact@8.1.0, and Preact-Router@2.5.1 for routing. My code looks like:
const MessengerPage = (props) => {
const AsyncMessenger = asyncComponent({
resolve: () => import('./Messenger'),
LoadingComponent: () => {
console.log('loading');
return (<div><Spinner /></div>);
}
});
return (
<AsyncMessenger { ...props } />
);
};
What I'm seeing is whenever my route changes (which, fwiw, causes the props to my above MessengerPage component to change), my Messenger component is unmounted, the loading component function is hit, and then the Messenger component is re-mounted. These unmount/re-mounts do not happen if I do not use asyncComponent.
Hey @rubencodes!
Yeah, it's an anti-pattern to create your async components within another component as you have done. Basically some "global" state is created for each instance. Also, your wrapping component does nothing but create an async component, so there is no need for it.
Try the following instead:
const MessengerPage = asyncComponent({
resolve: () => import('./Messenger'),
LoadingComponent: () => {
console.log('loading');
return (<div><Spinner /></div>);
}
});
<MessengerPage foo="bar" baz="bob" />RE: the "Also", yeah the actual component is slightly more involved, I just tried to simplify it here to the simplest example that still gave me the issue. I will try creating it outside the component! Thanks 😃
I thought that might be the case. Okay, sure thing. If you can describe the nature of the configuration you are trying to achieve I am happy to advise. 😊
I think I got it figured out! I just moved the asyncComponent calls outside of my main component, and it looks like it's working perfectly now! Thanks so much!
I'm running into the same problem. On the client side, I thought if I use
// note: This prevents the "flash" from happening.
asyncBootstrapper(app)
.then(function () {
ReactDOM.render(app, document.getElementById('root'));
});Then the rendering of the app should only happen after the app has been "walked" by the react-tree-walker. By then all of the bundles should already been loaded.
But this doesn't seems to be the case. The child link still flashes between the server-rendered page and the client-side code replacing it with the identical html node.
@rubencodes I'm using the asyncComponent to wrap the sub-pages (child routes). What do you mean exactly by "move [...] calls outside of my main component"?
Thanks in advance.
@rubencodes @ctrlplusb Hey guys do you guys have any intuition on the source of the flash? I am using the asyncBootstrapper call back already, which I thought should defer the ReactDOM rendering until the entire tree has been walked (and resolved).
but the flash seem still there. So I'm a bit baffled.