React server side rendering checksum warning - reactjs

I have a file upload component.
IE8: Using iframe for file upload.
Chrome: Using FormData
When doing server rendering, iframe is created in HTML.
When Chrome loads the page, there's no iframe.
So the waring is caused: Warning: React attempted to reuse markup in a container but the checksum was invalid
My question: How to handle this case?

You can fix this. Whether or not you should is another question...
Whatever it is that's putting the <iframe> in the page (or not) is doing so before React is running its first render cycle. You can prevent this (and anything else that modifies the DOM) in your main components componentDidMount() method.
There is a more complex approach of getting the userAgent string on the server and rendering appropriately there (Radium does this).
However, that warning is harmless. It is not shown with the production (minified) version of React so only affects the development experience. In my opinion I'd say leave it as is rather than push more complex code into production because of a warning in development. Maybe just try and get the server to default to not doing the iFrame.

Related

Server side rendering react - Virtual DOM?

I recently started looking into SSR(Server side rendering) and I am impressed with its advantages. To name a few Load times, SEO, No javascript configuration.
However I am trying to understand if react server side rendering is worth it.
React is known for its Virtual DOM manipulations but using react with server side rendering will not give benefits of reactJs.
Can some one shed your ideas on using reactJS for server side rendering?
Using server-side rendering in React does not imply that React will not be used on client-side.
One of completely valid approaches is to start with client-side rendering only. In this case you have to setup a single HTML element in your HTML file that will become a hook for React once it loads.
Just to give you an example, let's say we have an <div id="root"></div> element in index.html file that will be served if we HTTP GET / path on our server. Initial document (in our case index.html) should also reference javascript file that includes React and our code. It can be done by adding something like <script type="text/javascript" src="/index.js"></script> just before </body> tag.
At some point while index.js is executed, ReactDOM.render() method is called (note: we are in the browser right now) - this is a moment in time when React looks for a div element with root id attached in a document. After it's found, it becomes react-root - component tree is mounted under this element and managed by React (ie. virtual DOM, event handlers, state updates).
Please note that this approach requires that at least one javascript file is fetched, parsed and executed before browser can render anything meaningful (other than an empty div) to a user. For some scenarios, this is not acceptable and this is where SSR (server-side rendering) can help.
Server-side rendering requires that you have JavaScript runtime environment available on your server. One of the popular choices is Node.js (others include for example Nashron for JVM).
In approach, you execute React on the server and use ReactDOMServer.renderToString() (or ReactDOMServer.renderToNodeStream()) method to generate HTML response that is sent to the client - instead of an almost empty response with just one placeholder div as previously, now you can send all the markup that will be generated from your component tree (important note here is that in React 16.4(+) only UNSAFE_componentWillMount lifecycle method is called on server-side). After the initial response with a document is sent to the client, browser can render the initial markup before index.js even finishes downloading. Once it does, ReactDOM.hydrate() method kicks in. Hydration is a process of using existing server-side rendered markup and "watering" it with javascript goodies like event handlers. After it's done, this component tree is now completely managed by React with all the benefits.
Please note that in SSR, exactly the same component tree is rendered on a server-side and that's then hydrated on a client-side.
Of course, React can also be used instead of templating engines as a very powerful static HTML markup generator. All you need to do is to render the markup on the server with ReactDOMServer. renderToStaticMarkup() and send it to the client. It should be noted that this approach has a significant performance impact (https://malloc.fi/performance-cost-of-server-side-rendered-react-node-js) and uses a very limited number of React features.

Server side rendering with devextreme and material ui #react16

After refreshing the page (and going through my ssr) it looks like none of the css is sustained unless I navigate through my app and get back to it Or even click some elements. Are there any examples of how this is done correctly?
Im using the exact same code from the controlled 'react material ui grid' example:
https://github.com/kkotwal94/DrivingService (develop branch) <- where the component is under components / demoBase, and the SSR is under server/render/pageRender.jsx. I use the material ui example for how this is done. I utilize demo grid in Students.jsx.
Here is a pic of what happens post refresh:
Everything else renders fine (all other pages) in production mode and dev mode. I have no clue what im missing here. It looks like the jss-in-css is mapping incorrectly.
I found that reverting back to pre-React 16 everything began to work again SSR and what not, however i cant use dx-react-grid project since it requires 16. Kind of in a wackamole, still investigating where i goofed.
TEST
http://transportation.kkotwal.me/
I hosted it, if you click on login you can log in with yea#yea.com, password: 123, or you can just sign up where the username has to be a email it doesnt matter. After wards if you navigate to the students button on the navigation (if you click on transportation tracker after logging in you should be back to the root page / view). You will see the dev extreme controlled grid example.
If you hit refresh on that page you will see all the css is messed up. In case you arent sure what the page is: http://transportation.kkotwal.me/students. The source is here: https://github.com/kkotwal94/DrivingService/tree/UpdateReact . The server side rendering is located https://github.com/kkotwal94/DrivingService/tree/UpdateReact/server/render. The component for the devExtreme component is called DemoBase.jsx in the components folder, and the container that renders this is https://github.com/kkotwal94/DrivingService/blob/UpdateReact/app/containers/students/Students.jsx.
I guess you're already aware that React 16 came with lots of improvements to server-side rendering. The update came with additional server-side render methods like renderToNodeStream().
The official guide on upgrading React from 15 to 16 mentions that it should have no issues, with minor exceptions. One of those exceptions is a break change exactly when you hydrate a server-rendered container:
Hydrating a server-rendered container now has an explicit API. If you’re reviving server-rendered HTML, use ReactDOM.hydrate instead of ReactDOM.render. Keep using ReactDOM.render if you’re just doing client-side rendering.
Having that in mind, I'd search in your project (and possibly in third-party libraries as well) for some ReactDOM.render that was missed to be changed to ReactDOM.hydrate while upgrading React to version 16.
this is probably the issue at server side code and your nodejs script.
Reason #1:
if you are using material ui version 4.x then you should look at their ssr documentation
in material ui version 3.x or below that we use
JssProvider from 'react jss/lib/JssProvider';
however this is no more required, your both github links are broken , kindly check ssr code of yours and compare it with material-ui documentation
Reason #2:
you have to refer to your build folder for your expressjs
app.use(express.static(path.join(__dirname, '../../build')));
app.use(express.static(path.join(__dirname, 'public')));
this could be another reason and if this is missing then check that your componentDidMount also will not be invoked, so client side rendering won't be happening, however for ssr both client side and server side rendering has to happen
For complete code on SSR kindly refer this link

Prevent mounting/initial rendering of a server rendered react component

I'm using a custom tool similar to react-snap to create a snapshot of my app at build time, as recommended in the create-react-app docs. This generates a static server-rendered version, which I can deploy behind nginx without running react on the server. This works fine.
I'm also using code-splitting to lazily load some components to reduce the initial JS payload. (I use react-loadable, but I'm willing to change that if needed.) It works fine when creating the snapshot, and the HTML is generated correctly, which the user receives correctly, and everything is displayed fully server-rendered without even downloading any JS yet. This is great.
However, during rehydration on the client, the import(...) call for the async loaded component hasn't yet been fired. Meanwhile, the DOM already has the stuff that has to be rendered, from the snapshot.
In this scenario, is there a way to prevent the initial render of a component during mounting, since I already have the content in the DOM?
Also, is it possible to have react's hydration logic run after the import is complete, so that I can prevent any flicker even after the import is complete?
If it matters, the lazy-loaded components are infrequently used routes, managed by react-router.

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:"

How to make a server rendering with part of the code run only on a client?

I have window dependency in some of modules I use, so I cannot render part of my app on a server. However the content send from a server should be the same as a content rendered on a client first time, otherwise there will be a: "React attempted to use reuse markup in a container but the checksum was invalid" warning.
Seems like I need to do some workaround, render the content from a server and then, after component is mounted, render a client only part. Similar issue described here.
I feel this is the best solution, however eslint from AirBnB throws an error that changing state in componentDiMount is not good.
Do you have better ideas?

Resources