ReactJS: checksum was invalid - reactjs

I'm receiving this error, because server renders version of the webapp for not-authenticated users, which means some of UI elements are absent. Client side retrieves locally stored user token, then automatic authentication happens and client side renders slightly different DOM. The logic is ok, right? But how do i make this error stop popping up?
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) d=".c4gd6urcw.2.0"><noscript data-reacti
(server) d=".c4gd6urcw.2.0"><div data-reactid=".c

You could use cookies to store the token so the server can read them and handle the authentication there. Or, if you're set on keeping it in LocalStorage, as long as you trigger a secondary render after the initial that handles the login it should satisfy React. The warning is that it has to rerender your entire app since the checksums don't match. Maybe something like this?
componentDidMount() {
// this is only called client side after the server render
if (localStorageHasToken) {
handleAuth()
}
}
The goal is just to make that initial client render match what the server sent it initially. Throwing the authentication in a new process should ensure the initial checksums match and then the rest is just basic React rerendering.

Related

React-router with Saga Server-side render redirect

The issue is that I have an initial fetch request that gets the query string from the URL and makes a request to get a specified product page.
The same logic and routing is used on the client side and server side.
The API request gets executed in redux-saga, but, when it fails (no matching product), the site is already on the /product route, and so redirect needs to happen.
On the client-side this is very easy, as it can be redirected dynamically using browserHistory or just window.location.href, but on the server, i would have to pass down the res object and use res.redirect and, possibly, use two different redirect functions with this approach.
The other solution is to catch this in a topmost fashion; on express index.js during ReactDOMServer.renderToString(component), and also on the client side endpoint when it fails - with different logic. For example, a 404 view with express redirect. But, because saga is not the topmost in hierarchy anyway, throwing this 404 and catching it in the uppermost context (express server) requires passing it up and up in a very "dirty" try/catch way.
Any suggestions how to tackle that in terms of correctness? I really don't want to have routing logic doubled up on express side, so I'd rather have it handled nicely with isomorphic code.
You are probably exposing your main state to be picked up by the front-end code. Any calls that are returned from sagas can update that state. We are using a set404() and set301() actions when redux saga does not return the data we want. These actions are triggered and they set return404: true or return301: true in the main state object. So before rendering our app to string we inspect that object. If any of these are present we return a relevant response from the server.

React Redux Server side rendered rerendering on client again

I created server side rendering with approach described in redux's official site, everything is great, but on client side it rendering components again, and this is not good I think. I am passing same state from server to window.__STATE__ variable and passing this to my client side createStore method as initial state, but it rerendering again.
Also please write in comments which part of code is needed to you, if so.
I am not providing since it is very similar to official page instructions code and there is no errors, just issue with rerendering, but as I understand it is not connecting to virtual DOM.
Please help me find valid way for handling this task.
Take a look at this example from the ReactGo project: https://github.com/reactGo/reactGo/blob/master/app/client.jsx#L22
They use a function onUpdate that has the conditional
if (window.__INITIAL_STATE__ !== null) {
window.__INITIAL_STATE__ = null;
return;
}
which prevents a duplicate fetches if __INITIAL_STATE__ is already defined. Your components rerendering may have something to do with the duplicate fetching.
Perhaps I am not understanding what you mean by re-rendering, but it is supposed to "re-render" on the client again. The way isomorphic works is that it renders the HTML on the server, and then the payload includes the initial state as well has the HTML markup - this way the browser "appears" to have faster page load times - since the UI is rendered even before the script is executed. Now once the HTML parsed and the script runs, React internally builds the virtual DOM and then compares it to the server generated DOM and wires up event listeners etc. It does not however, do a full re-render in that no new DOM elements should be created. If for any reason the client run of your React render results in a virtual DOM that is different from the generated server DOM, React will give you a warning.
"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:"

What happens with the state in a React isomorphic App

I am building an isomorphic app with React that must support users without JS.
I am new in this technology and I have a basic doubt:
The server can store the components states to emulate what React does in the client-side?
I imagine this flow when the user dont have JS:
The user click a button and send a request to the server.
The server recovers the state of the app and makes changes in it.
The components listen this changes and are rendered again.
Is it correct?
Assuming that you're using react-router :
The server aims to initialize your state, to provide it the default minimum values necessary to make your application work while getting an url.
For example, if you have an application in which you want to display a user list, let say on /users URL, when you'll send your first request, the server will store the users in the react state.
After that first load, you'll be working on the client side using react-router, and making XHR request.
However, if you refresh your page, the process will start again : first load initializing the state and then client side navigation.
EDIT : Explanations =>
When you want to use react on the server, this means that you use a Nodejs server. The fact is that react-dom provides a method called renderToString that transform a react jsx component into standard HTML.
This aims to load the first call faster
Why ?
When you load a "big" JS application on the client, you have some delay time, the time your browser needs to download your JS bundle.
Server side rendering aims to avoid that behaviour, or at least, to gives the feeling that the app starts faster.
In no case you can only use react, even if you use your server side renders. Why ? . Because your events on buttons, or asynchronous load on client, or keypress are in JS language.

React can be used on server side rendering. What does that mean?

I am new to React and Redux . Although i know that React is just a view layer . But i saw a term "React can be used on server side rendering". What does this mean and how it works behind the scene with nodejs.Can anyone help me in getting clear the fact that "What is server side render in react".
The react-dom package includes a server module. This module allows you render your react application to a simple HTML string with reactDOMServer.renderTostring(). Basically a snapshot of your view for a given set of props:
https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostring
Additionally this functions calculates a unique hash from the string it generated and appends it to the html. On the client side react can "pick up" the server generated HTML and use it as its "first render".
Though the client side first render and the server render need to produce the exact same output for react to pick it up on the client side. React can check this via the generated hash: The client side react will also generate a html string (without modifying the actual DOM, I think this is done only on the virtual DOM). Now it can also calculate a hash from its virtual DOM and compare it with the server rendered one. If they match, no rendering needs be done. If they don't, the client side react will throw away the server generated DOM and replace it with its version (and print out an error/warning).
In combination with redux this means in addition to rendering the HTML you need to pass down the state of your store (store.getState()) to the client. The client can then use this serialized state as an initial state when creating its instance of the redux store. This will lead to both renders (client + server) to match up.
If you don't need the client side to do anything and just want to create static markup on the server side, react-dom offers a renderToStaticMarkup() function:
https://facebook.github.io/react/docs/top-level-api.html#reactdomserver.rendertostaticmarkup

What is checksum in React and how to use it?

I'm reading this example of React server-side rendering. It states:
Try viewing the page source to ensure the HTML being sent from the server is already rendered (with checksums to determine whether client-side rendering is necessary)
Ok, I saw page source and there is indeed a data-react-checksum attribute:
<div data-reactid=".157rq30hudc" data-react-checksum="556954499">
And when I check the element in a browser console, it also has the attribute:
Then I decided to checked my site that uses React server side rendering too. And I see strange thing. Page source has data-react-checksum attribute but the element is a console doesn't.
Page Source:
<div class="activityOptionBox" data-reactid=".1l6uko4wt8g" data-react-checksum="168103090">
Console:
What does it mean? What for checksum and how to read/use it?
The checksum is used internally by React on the client, when using server rendering via ReactDOM.renderToString, to determine if the output from the server matches the output from the client. If it does, React can transparently upgrade the existing DOM from the server into a client-side app very efficiently. If it doesn't match, it means that the state and props to render on the server were different from the state and props to render on the client, and React must do a more expensive operation to initialize the client-side app.
I checked an app of mine, and it seems that—in at least some versions of React—the checksum attribute is removed from the element once the client-side application boots, though it is visible in the source code of the page.
Since the checksum is an internal consistency mechanism, you don't need to worry about it unless React detects that your server checksum and client checksum don't match, in which case it'll tell you via a warning or error in the console.

Resources