mikethehud
mikethehud

Reputation: 43

Redux async SSR: Empty store after fetching data

I am trying to dispatch an action to fill the store before sending the HTML to the browser on the server with React, Redux (w/ thunk) and Axiom.

server.jsx

/* ... */

const currentRoutes = routes.filter(route => matchPath(req.url, route));

const promises = currentRoutes.map((route) => {
  let fetchData = route.component.fetchData;
  return fetchData instanceof Function ? fetchData(store) : Promise.resolve(null)
});

// Check promises
Promise.all(promises)
  .then(response => {

    const context = {};

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

    const stylesheet = renderToString(
      <link rel="stylesheet" href="/static/styles.css" />
    );

    const helmet = Helmet.renderStatic();

    res.status(200).send(Template({
      markup: markup,
      helmet: helmet,
      initialData: serialize(store.getState()),
      stylesheet: (process.env.NODE_ENV == 'development') ? '' : stylesheet
    }))
  })
  .catch(err => {
    console.log('error', err);
  })

/* ... */

In my server.jsx, I am looking for the matching routes

Then I am dispatching in the route components static fetchData function. I am mapping the results into a const called promises.

I then check the promises, create the static page with renderToString() and send the data with my Template() function after serializing it.

However, all I receive in my window variable is my initial state from the reducer:

<script>
   window.__PROPS__ = {"experiences":{"fetching":true,"fetched":false,"all":[]}}
</script>

Here are the relevant code bits:

The Action

const fetchExperiences = () => {
  return function(dispatch) {
    dispatch({ type: "FETCH_EXPERIENCES_START" });

    axios.get(config.api.baseUrl+'/experiences/rows?order[start_date]=DESC')
      .then((response) => {
        let data = response.data && response.data.data;
            dispatch({ type: "FETCH_EXPERIENCES_FULFILLED", payload: data })
        })
      .catch(err => {
        dispatch({ type: "FETCH_EXPERIENCES_REJECTED", payload: err })
      })
  }
}

The Component

class Home extends React.Component {

    static fetchData (store) {
        return store.dispatch(fetchExperiences());
    }

    /* ... */

}

Looking forward to your answers - thank you so much in advance!

Upvotes: 1

Views: 721

Answers (1)

ekcr1
ekcr1

Reputation: 4514

In the fetchExperiences function, the axios.get(config.api... promise needs to go back to redux, so adding the missing return should fix it. i.e. return axios.get(config.api.baseUrl+'/experiences/rows?order[start_date]=DESC')

Upvotes: 1

Related Questions