Closed lukebarton closed 6 years ago
What is inside window.___REACT_DEFERRED_COMPONENT_MARKS
? Did it track loaded components properly? (babel plugin is required for this operation)
You can try to emulate babel plugin, like I did in tests
function importedWrapper(marker, name, realImport) {
return realImport;
}
const Another = importedComponent(() => importedWrapper('components/Another', 'mark1', import("./components/Another"));
It's value looks something like ['-15frra52']
(not exact, not on laptop
at present)
Any example to reproduce?
Could you add some random data-rnd
attributes to random divs to figure out which one React don't like.
https://www.dropbox.com/s/ygg5bdtu6psozry/smsc.zip?dl=1
$ yarn install && webpack
$ node dist/server/index.js
Should get the server running
Then visit http://localhost:1234/another
This is related to React 16.3 I've just updated dependencies and get the same.
Ok. There is 2 bugs here.
I've fixed the actual problem, but this warning is still exists. And I am not sure why. HTML before and after hydration is the same.
The HTML (for me) has always been the same before and after. That's why I raised this issue.
Are you sure the things you have changed are actually related, if the warning still persists?
There was a flickering of async component, I saw it, and I debug it - application was not waiting for Another
to be loaded. This is the thing I've fixed.
But still getting the error, regardless of Another position, but only when it exists.
I have to dig deeper.
I've found an issue. React 16.3 deprecated componentWillMount, and this changed the way Loader work. Will fix tomorrow. It is much harder to write enzyme test to catch it, that to fix it.
The problem was hydrate
itself.
If component was preloaded it will be reused on Loader creation, but the actual value will be set using setState.
This is ok for enzyme or frontend, as long setState inside contructor or lifeCycle method will lead to the right
state used in render.
In case of hydrate, look like this is bound to 16.3, "the current state" will be used on render. And it was just empty, resulting wrong rehydration. Wrong but invisible for the eye, as long correct state was already state, and changes will be applied before browser redraw.
v4.3.1
@theKashey I'm getting the exact same behavior on react 16.8.6 and react-imported-component 5.5.3
Did you fix this or is it something I can safely ignore as long as there is no apparent mismatch between server rendered and hydrated markup?
Thank you
This message from react is just about unexpected difference between server and client rendered code. Like - just don't match, by any reason.
Please look at your HTML coming from server, and the result HTML in the browser. That's the difference. Then we might think about "why".
If you have some example I could play with - just sent me a link, and I would handle the rest.
Well I have a monorepo and the concerning package is difficult to separate from the rest.
I can easily see what the server sends, but what is the proper way to extract the final js-hydrated html? I copied outerHtml from the render/hydration root div and the server response into diff tool and there was no difference.
I think I'm doing something fundamentally wrong with react-imported-components. When I export component to be loaded by react-imported-component:
const Test = () => 'test';
export default Test;
and re-export it as a route component:
import importComponent from 'react-imported-component';
const Test = importComponent(() => import(/* webpackChunkName: "test-component" */ './TestComponent'), {});
const TestRoute = {
component: <Test />,
};
export default TestRoute;
App component used with hydrate:
import { Grommet } from 'grommet';
const App = ({children}) => (<Grommet theme={customTheme} full>{children}</Grommet>);
export default App;
client.js
import ReactDOM from 'react-dom';
import { rehydrateMarks } from 'react-imported-component';
import route from './TestRoute';
import App from './App';
const app = <App>{route.component}</App>;
rehydrateMarks().then(ReactDOM.hydrate(app, document.getElementById('root'));
I Get server rendered html:
<div id="root"><style data-styled="cqQlmF" data-styled-version="4.3.2" data-styled-streamed="true">
/* sc-component-id: sc-global-552078406 */
/* styled-components styles... */
</style><div class="StyledGrommet-sc-19lkkz7-0 cqQlmF">test</div></div>
Final html after rehydrateMarks().then(ReactDOM.hydrate()):
<div id="root"><div class="StyledGrommet-sc-19lkkz7-0 cqQlmF">test</div></div>
And console output:
Warning: Did not expect server HTML to contain the text node "test" in <div>.
Client App and ssr live in 2 separate packages. When App is built with webpack, it builds a version for browser (code splitting enabled) and a version with target: 'node' (a single bundle file without code splitting) for inclusion by ssr which sends the rendered html down to the client as a stream together with interleaveWithNodeStream from styled-components.
You shall compare content of “root” element just before hydration, and just after. I am not sure that’s the problem, as long as “test” should be expected to be inside the only rendered div. Could you share the problematic example, or just final bundles to play with?
I replaced
rehydrateMarks().then(ReactDOM.hydrate(app, document.getElementById('root'));
with:
rehydrateMarks().then(() => {
ReactDOM.hydrate(app, document.getElementById('root'));
});
The warning is now gone and most importantly the flicker when hydrating, is gone as well.
Thank you :)
😅of course, you were calling hydrate too early.
I get this error when I use
importedComponent
andhydrate()
to do SSR hydration. Both the SSR html and hydrated html appear identical and I do not get any error if I import the component normally.