React has built-in support for server-side rendering, try it yourself:
import React from 'react';
import ReactDOMServer from 'react-dom/server';
const App = <div>Hello world</div>;
ReactDOMServer.renderToString(App);
// (only React v <= 15 has checksums, >= 16 no longer uses checksums)
// "<div data-reactroot="" data-reactid="1" data-react-checksum="999625590">Hello World</div>"
and Headless-Render-API.com has special support for React versions <= v16 - it will return the output from ReactDOMServer.renderToString
. But if that throws an error, it falls back to normal HTML output (which is almost the same).
ReactDOMServer.renderToString
, be aware that componentWillMount
is the only lifecycle method called during renderToString, so any behavior that depends on other lifecycle methods will not workcomponentDidMount
or the constructor
for making AJAX calls - but this only applies to React versions >= 16. So if you're on <= 15, use componentWillMount
__PRELOADED_STATE__
__PRELOADED_STATE__
was implemented https://github.com/emilong/makeup/commit/92635de9aeba7df0e21319a1af218ee07612c05c__PRELOADED_STATE__
If using react-helmet >= v5, make sure you have the defer
setting enabled
<Helmet defer={false}>
or
Helmet.defaultProps.defer = false;
see https://github.com/nfl/react-helmet/pull/297 or https://github.com/nfl/react-helmet/issues/336
renderToString
and make sure it worksThe actual error in your JavaScript console reads:
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
This means that the checksum is being generated but the checksum generated on the server is not matching the checksum generated on the client.
The most common root cause is you're fetching async data, and Prerender.cloud's Ajax-Preload monkeypatch is caching some of that data, but even though it's cached, there's still a "nextTick" before the cache is returned, which is just enough time for React to render without any state being available.
To fix it, you'll have to save the app state to window.__PRELOADED_STATE__
or window.__PRELOADED_STATE_PLAIN__
, see our docs on state