Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Server-side rendering with React with a randomly generated string?

I'm trying server-side rendering for the first time in my React/Redux app. An issue I'm having right now is that I need the initial state to have a randomly generated string and then pass it as a prop to my main App component. This is obviously causing an issue because it's generating different strings for the client and server. Is there something I can do to stop this issue from happening?

Basic structure to help with understanding:

App.js

import React from 'react';
import { connect } from 'react-redux';

const App = ({ randomStr }) => (
  <div> 
    <p>{randomStr}</p>
  </div>
);

const mapStateToProps = (state) => ({
  ...
});

const mapDispatchToProp = (dispatch) => ({
  ...
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

And my reducer:

reducer.js

import { generateString } from '../util';
import { NEW_STRING } from '../constants';

const stringReducer = (state = generateString(), action) => {
  switch (action.type) {
    case NEW_STRING:
      return generateString();

    default:
      return state;
  }
};

export default stringReducer;

As you can see, I'm getting the randomStr from my redux store and rendering it, but it is different in client and server. Any help would be appreciated!

like image 762
Saad Avatar asked Jul 21 '16 06:07

Saad


People also ask

Can React be used for server-side rendering?

Yes! This is where server-side rendering for React comes in. In this article, I want to introduce you to server-side rending (SSR) with React, reasons to use it, and some popular frameworks for rendering React on the server side.

Is ReactJS rendered server-side or client-side?

By default, your React app will be client-side rendered. This means basically, all of the source code will live in JavaScript files referenced in a single HTML file that initializes your app.


1 Answers

When you're generating the store and your initial state on the server side, the client should not do the same and try to regenerate the data.

You need to generate your store and your initial state only once (on the server) and pass it down to the client. To do that, you need to inject it in the initial component you'll be rendering.

The most common approach is to add a <script> tag and attach the state to your window, for instance in window.__initialState.

For example, if you're using ReactDOM.renderToString on the server side to render your initial component called Html, you can:

const html = ReactDOM.renderToString(<Html initialState={initialState} />);

Then, in your Html component, you can inject this data so the client can use it later:

<script dangerouslySetInnerHTML={{ __html: `window.__initialState=${JSON.stringify(this.props.initialState)};` }}/>

After that, on the client side, you can use window.__initialState to get your data back and you'll end up with the same data on the server and the client.

like image 94
HiDeo Avatar answered Oct 18 '22 16:10

HiDeo