Rama
Rama

Reputation: 23

SSR React with data for redux store

How possible is it to populate store (on server side) with already fetched data without triggering API (dispatch(action))?

The steps:

  1. Client going to website with link /users
  2. On the server I take /users and pass it to the StaticRouter
  3. On this step the documentation tells that, I need to dispatch all actions (aka function loadData) in all components (specific for this route) recursively and store fetched data in redux store.

But I already have all necessary data for this and I don't want to trigger API.

Thanks in advance for any help.

Upvotes: 2

Views: 1382

Answers (1)

mehmetseckin
mehmetseckin

Reputation: 3107

You could construct the application state manually using existing data, and create the redux store from that application state, and pass it over to the client side in a global variable.

The client side then would read the state and rehydrate the redux store. The following is an untested illustration of this:

Server Side

// ...
// import stuff from places
// ...

// Readily available user data
const users = [{ "_id": 1000, "name": "John Doe" }, { "_id": 2000, "name": "Jane Brown" }];

app.get('/users', (req, res) => {

    const context = {};

    // Manually construct the redux state
    const state = { users: users };

    // Create redux store with existing state
    const store = createStore(
        JSON.stringify(state)
    );

    const reactDomString = renderToString(
        <Provider store={store}>
            <StaticRouter context={context} location={req.url}>
                <App />
            </StaticRouter>
        </Provider>
    );

    res.end(`
        <div id="app">${ reactDomString }</div>
        <script>
            window.REDUX_DATA = ${ JSON.stringify(state) }
        </script>
        <script src="./app.js"></script>
    `);
});

Client Side

// ...
// import stuff from places
// ...

// Pick up the data from the SSR template
const store = createStore(window.REDUX_DATA);
const appContainer = document.getElementById("app");
ReactDOM.hydrate(
    <ReduxProvider store={store}>
        <Router>
            <Layout />
        </Router>
    </ReduxProvider>, 
    appContainer
);

Upvotes: 2

Related Questions