Server-side rendering with React with a randomly generated string?
Asked Answered
R

2

6

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!

Replicate answered 21/7, 2016 at 6:27 Comment(5)
what's the code of generateString ?Sherrod
"Things you should never do inside a reducer: Mutate its arguments; Perform side effects like API calls and routing transitions; Call non-pure functions, e.g. Date.now() or Math.random()." And generateString that takes no arguments and returns a string is either a constant or impure.Locust
Oh, I see what you're saying. I fixed my code so that i'm not using generateString() inside the reducer anymore, i do it as the initial state when I create the store. However, I still have the issue that it's generating differently for the client and server, so that when it is passed down as a prop it is causing issues. Is there any way around this?Replicate
If you're creating the store (and its initial state) on the server, then why is it regenerating on the client? The server's version of the store should be getting passed to the client, along with the generated string.Eudemonics
@meh_programmer just push the initial state you generated on the server to the client.Frenulum
N
5

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.

Neurotomy answered 24/7, 2016 at 8:59 Comment(0)
E
0

Let's spread the word! React created a hook for it called useId since react 18. https://react.dev/reference/react/useId

Purpose is creating consisted random values between [server, client] side rendering.

Ecosphere answered 14/11, 2023 at 7:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.