8

I am currently using the below server side rendering logic (using reactjs + nodejs +redux) to fetch the data synchronously the first time and set it as initial state in store.

fetchInitialData.js

  export function fetchInitialData(q,callback){
      const url='http://....'
      axios.get(url)
          .then((response)=>{
              callback((response.data));
          }).catch((error)=> {
            console.log(error)
      })
  }

I fetch the data asynchronously and load the output in to store the first time the page loads using callback.

handleRender(req, res){
 fetchInitialData(q,apiResult => {
    const data=apiResult;
    const results ={data,fetched:true,fetching:false,queryValue:q}
    const store = configureStore(results, reduxRouterMiddleware);
     ....
    const html = renderToString(component);
    res.status(200);
    res.send(html);
    })
}

I have a requirement to make 4 to 5 API calls on initial page load hence thought of checking to see if there is an easy way to achieve making multiple calls on page load.

Do I need to chain the api calls and manually merge the response from different API calls and send it back to load the initial state?

Update 1: I am thinking of using axios.all approach, can someone let me know if that is a ideal approach?

AntonNiklasson
  • 1,719
  • 1
  • 15
  • 28
Learner
  • 2,303
  • 9
  • 46
  • 81
  • Be careful when using Promise.all approach, because you make multiple requests and if one Promise get's revoked it all get's revoked. – Risto Novik Oct 25 '16 at 18:08
  • This is probably not what you are needing immediately, but GraphQL could potentially solve these types of issues if you have access to that layer and it's early enough in your project. http://graphql.org/ – Jazzy Oct 25 '16 at 23:36

3 Answers3

7

You want to make sure that requests happen in parallel, and not in sequence.

I have solved this previously by creating a Promise for each API call, and wait for all of them with axios.all(). The code below is basically pseudo code, I could dig into a better implementation at a later time.

handleRender(req, res){
  fetchInitialData()
    .then(initialResponse => {
      return axios.all(
        buildFirstCallResponse(),
        buildSecondCallResponse(),
        buildThirdCallResponse()
      )
    })
    .then(allResponses => res.send(renderToString(component)))
}

buildFirstCallResponse() {
  return axios.get('https://jsonplaceholder.typicode.com/posts/1')
    .catch(err => console.error('Something went wrong in the first call', err))
    .then(response => response.json())
}

Notice how all responses are bundled up into an array.

The Redux documentation goes into server-side rendering a bit, but you might already have seen that. redux.js.org/docs/recipes/ServerRendering

Also checkout the Promise docs to see exactly what .all() does.developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Let me know if anything is unclear.

AntonNiklasson
  • 1,719
  • 1
  • 15
  • 28
0

You could try express-batch or with GraphQL is another option.

Hosar
  • 5,163
  • 3
  • 26
  • 39
0

You also could use Redux-Sagas to use pure Redux actions to trigger multiple api calls and handle all of those calls using pure actions. Introduction to Sagas

Austin Hunt
  • 136
  • 6