React-apollo: Preserve rendering order of components in getDataFromTree function

Created on 16 Mar 2017  Â·  4Comments  Â·  Source: apollographql/react-apollo

We are getting the React checksum invalid when using graphql HOC with Fela library. Fela relies on the execution order to generate atomic classes.

Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) >

Steps to Reproduce

Consider the following structure of components which uses react router v2/v3
|---- App
    |---- Nav
    |---- {router children}
                    |-----RegionsPage
                                        |---- RegionList*
                                                            |----RegionListItem
    |---- Footer

Components with asterixs are connected with graphql queries.

Example code at https://github.com/ravikiran438/react-production-starter/blob/develop/common/components/App.js

  1. add className={renderer.renderRule(styles.footer)} to footer element of Footer component.

Buggy Behavior

using renderRule in className for all the components after react router children for that path.. for example the /regions has a graphql component and is a children to App component and Footer component is after children and has className using rendererer then it causes the mismatch

Here is generated css for both server side and client side paste.ee The styles are generated but as you can see its the last there classes .ah .ai .aj are shuffled

Expected Behavior

The execution order should be in sync on both server and client side.

Version

Most helpful comment

Try calling renderer.clear() in between getDataFromTree() and renderToString(). This should work 👍

So roughly:

const renderer = createRenderer();
const jsx = <MyApp/>;
await getDataFromTree(jsx);
renderer.clear();
return renderToString(jsx);

The reason you need to call renderer.clear() is that getDataFromTree() will do a lightweight render of your app in order to get all of the data queries you are planning to execute. This lightweight render generates all of Fela’s CSS classes. By the time you render a second time, Fela’s internal “offset” for CSS classes is off by one render, so you need to reset the internal offset.

All 4 comments

The only workaround I know of is to use fela-monolithic enhancer https://github.com/rofrischmann/fela/tree/master/packages/fela-monolithic

Not a permanent solution though.

Try calling renderer.clear() in between getDataFromTree() and renderToString(). This should work 👍

So roughly:

const renderer = createRenderer();
const jsx = <MyApp/>;
await getDataFromTree(jsx);
renderer.clear();
return renderToString(jsx);

The reason you need to call renderer.clear() is that getDataFromTree() will do a lightweight render of your app in order to get all of the data queries you are planning to execute. This lightweight render generates all of Fela’s CSS classes. By the time you render a second time, Fela’s internal “offset” for CSS classes is off by one render, so you need to reset the internal offset.

@calebmer it works! Thank you, sir!

@calebmer Awesome it works like a charm. Thank you!

Was this page helpful?
0 / 5 - 0 ratings