Do you want to request a feature or report a bug?
Bug maybe?
What is the current behavior?
When Server side rendering is enabled on the server side along with code splitting on the client side the app throws a warning
vendors.741d122c240b5639589c.js:701 Warning: Did not expect server HTML to contain a <div> in <div>.
printWarning @ vendors.741d122c240b5639589c.js:701
warning @ vendors.741d122c240b5639589c.js:725
warnForDeletedHydratableElement @ vendors.741d122c240b5639589c.js:20946
didNotHydrateInstance @ vendors.741d122c240b5639589c.js:31362
deleteHydratableInstance @ vendors.741d122c240b5639589c.js:26084
popHydrationState @ vendors.741d122c240b5639589c.js:26244
completeWork @ vendors.741d122c240b5639589c.js:25232
completeUnitOfWork @ vendors.741d122c240b5639589c.js:26807
performUnitOfWork @ vendors.741d122c240b5639589c.js:26906
workLoop @ vendors.741d122c240b5639589c.js:27008
callCallback @ vendors.741d122c240b5639589c.js:15625
invokeGuardedCallbackDev @ vendors.741d122c240b5639589c.js:15664
invokeGuardedCallback @ vendors.741d122c240b5639589c.js:15521
performWork @ vendors.741d122c240b5639589c.js:27126
scheduleUpdateImpl @ vendors.741d122c240b5639589c.js:27511
scheduleUpdate @ vendors.741d122c240b5639589c.js:27450
scheduleTopLevelUpdate @ vendors.741d122c240b5639589c.js:27721
updateContainer @ vendors.741d122c240b5639589c.js:27751
(anonymous) @ vendors.741d122c240b5639589c.js:31431
unbatchedUpdates @ vendors.741d122c240b5639589c.js:27582
renderSubtreeIntoContainer @ vendors.741d122c240b5639589c.js:31430
hydrate @ vendors.741d122c240b5639589c.js:31452
48 @ bundle.741d122c240b5639589c.js:304
__webpack_require__ @ manifest.741d122c240b5639589c.js:55
47 @ bundle.741d122c240b5639589c.js:254
__webpack_require__ @ manifest.741d122c240b5639589c.js:55
webpackJsonpCallback @ manifest.741d122c240b5639589c.js:26
(anonymous) @ bundle.741d122c240b5639589c.js:1
When code splitting is disabled the warning goes away.
What is the expected behavior?
An error message should not be shown
In my serverMarkUp.js
const markup = ReactDOMServer.renderToString(
<StaticRouter location={request.url} context={context}>
<App />
</StaticRouter>
);
In my App.js
import { Route, Switch } from 'react-router-dom';
import About from './pages/AboutPage';
import Homepage from './pages/Homepage';
import LearnMorePage from './pages/LearnMorePage';
class App extends Component<{}, {}> {
render() {
return (
<div>
<Switch>
<Route exact path={RoutingConstants.HOME} component={Homepage} />
<Route path={RoutingConstants.LEARN_MORE} component={LearnMorePage} />
<Route path={RoutingConstants.ABOUT_US} component={AboutPage} />
</Switch>
</div>
);
}
}
Now moving over to the Client side
My index.js
import { hydrate } from 'react-dom';
import ClientApp from './clientApp';
hydrate(
<BrowserRouter>
<ScrollHandler>
<ClientApp />
</ScrollHandler>
</BrowserRouter>,
document.getElementById('root')
);
My ClientApp.js
type AsyncComponentState = {
component: any
};
function asyncComponent(importComponent: Function) {
class AsyncComponent extends Component<{}, AsyncComponentState> {
constructor(props) {
super(props);
this.state = {
component: null
};
}
/*
* This issue is an open issue related to flow
* https://github.com/facebook/flow/issues/1803
*/
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
render() {
const C = this.state.component;
return C ? <C {...this.props} /> : null;
}
}
return AsyncComponent;
}
const About = asyncComponent(() => import('./pages/About'));
const Homepage = asyncComponent(() => import('./pages/Homepage'));
const LearnMorePage = asyncComponent(() => import('./pages/LearnMorePage'));
class ClientApp extends Component<{}, {}> {
render() {
return (
<div>
<Switch>
<Route exact path={RoutingConstants.HOME} component={Homepage} />
<Route path={RoutingConstants.LEARN_MORE} component={LearnMorePage} />
<Route path={RoutingConstants.ABOUT} component={About} />
</Switch>
</div>
);
}
}
export default ClientApp;
Now when i change my index.js to include <App /> instead of <ClientApp /> (i.e disable code splitting i dont get any warning).
Am i missing something here ? 馃
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
React 16
I found a similar qn here on stackoverflow. Unfortunately there was no reply :(
Can you please provide a minimal example without React Router or HOCs? Neither should be essential to the problem you have. It鈥檚 hard to tell what鈥檚 going on when there are multiple indirections.
Can i make a small repo for this.. with the above case will that work?
Sure, if it reproduces the problem and doesn't have third party dependencies.
I'll close since we don't have a full repro. If you create one, please reopen or file a new issue. Thanks!
Alright so i solved this last week, just thought i should post the solution incase someone else is stuck.
I was attempting code splitting at a route level eg, bundles for HOME, ABOUT_US, as all these bundles were being dynamically imported (async nature) for a brief moment when you call ReactDOM.hydrate the screen would flicker / go blank. This is what caused the warning, cause the warning is thrown if the DOM tree on the server and on the client are different. So solution was call hydrate inside a promise after the bundle has been loaded. or follow https://github.com/thejameskyle/react-loadable The docs are really good. Explains step by step.
@nitish24p doesn't this mean you are delaying when page becomes interactive?
ideally the above fold critical content should become interactive sooner, then lazy loaded (typically below fold less important) stuff download, then rehydrate. whole point of lazy loading is to make critical stuff interactive sooner.
@dalimian possible.. i haven't put perf markers on my app so wont be able to comment. Will try it out though.. :)
please provide solution for this problem .
I used 'Loadable.preloadReady' before hydrate, but the problem is also.After I use 'Loadable.preloadAll' instead of 'Loadable.preloadReady' in client render, this problem done.
had written this in an article.. might help someone https://medium.freecodecamp.org/code-splitting-with-higher-order-components-4ac8f094b059
Most helpful comment
Alright so i solved this last week, just thought i should post the solution incase someone else is stuck.
I was attempting code splitting at a route level eg, bundles for
HOME,ABOUT_US, as all these bundles were being dynamically imported (async nature) for a brief moment when you callReactDOM.hydratethe screen would flicker / go blank. This is what caused the warning, cause the warning is thrown if the DOM tree on the server and on the client are different. So solution was callhydrateinside a promise after the bundle has been loaded. or follow https://github.com/thejameskyle/react-loadable The docs are really good. Explains step by step.