Tomek Buszewski Tomek Buszewski - 1 year ago 218
React JSX Question

Isomorphic React - checksum doesn't match

I am learning how to render my React site on server. So far, I have managed to do the render with async data, but I have a problem when I include the script (ergo, when I want to have isomorphic app):

Warning: React attempted to reuse markup in a container but the checksum was invalid (...):
(client) <!-- react-empty: 1 -
(server) <div class="blah" dat

I can't figure why this is happening. My code is as follows:



import express from 'express';
import path from 'path';

import React from 'react';
import { renderToString } from 'react-dom/server'
import { match } from 'react-router'
import { ReduxAsyncConnect, loadOnServer, reducer as reduxAsyncConnect } from 'redux-connect'
import { Provider } from 'react-redux';

import routes from './app/routes';
import store from './app/store';

const app = express();
const port = 3100;

const createPage = (html) => {
return `<!doctype html>
<div id="app">${html}</div>

<script src="/public/index.js"></script>

app.get('/', (req, res) => {
match({ routes, location: req.url }, (err, redirect, renderProps) => {
loadOnServer({ ...renderProps, store }).then(() => {
const appHTML = renderToString(
<Provider store={store} key="provider">
<ReduxAsyncConnect {...renderProps} />

const html = createPage(appHTML);
}).catch((e) => { console.log(e); })

app.use('/public', express.static(path.join(__dirname, 'public')));
app.use('/data', express.static(path.join(__dirname, 'data')));



import React from 'react';
import { Router, Route, browserHistory } from 'react-router';
import { ReduxAsyncConnect, asyncConnect, reducer as reduxAsyncConnect } from 'redux-connect'
import App from './Components/App';
import { Provider } from 'react-redux';

import store from './store';

const routes = (
<Provider store={store} key="provider">
<Router render={(props) => <ReduxAsyncConnect {...props} />} history={browserHistory}>
<Route path="/" component={App}/>

export default routes;

main (client)

import React from 'react';
import { render } from 'react-dom';
import routes from './routes';
import { match } from 'react-router'

match({ routes, location: '/' }, () => {
render(routes, document.getElementById('app'))

I'm sure that there is a little bug somewhere that produces this error, but I can't seem to find it.

Answer Source

I guess the client side is missing the state to render the app correctly. You need to pass down the app state to the client. This is also called rehydration.

You can do this by serializing your state on the server and sending it down as a JSON string with the rendered html. On the client side you can parse the serialized state and use it as an initial state when creating the store. This will result in both renders, the server and the first client side one, to produce the same markup --> the checksum equals.

Check the second argument you can pass to createStore

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download