Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Redux - Wait until data is loaded

Tags:

reactjs

redux

I'm using Redux (+ thunk) to fetch data from my API. I implemented a Data Fetcher component that calls all the actions and once done, dispatches a LOADED. In my actual main component where I render content, I wait until isLoaded flag in the props is set to true.

Here's the method in the data fetcher:

const fetchData = () => {
    if (isAuthenticated) {
        const p = [];
        p.push(fetchDataSetOne());
        p.push(fetchDataSetTwo());
        Promise.all(p).then( () => setHasLoaded() );
    }
}

Each of those fetch methods returns an axios promise, in which I dispatch once retrieved like so:

export const fetchDataSetOne = () => dispatch => {
  return axios.get(`${API_URL}/dataSetOne`)
    .then(res => {
        dispatch({
            type: FETCH_ALL_DATA_SET_ONE,
            payload: res.data.docs
        });
    });
};

In my component's render function I only render the content when loaded (which is set by the LOADED dispatch from the setHasLoaded action) like so:

{ hasLoaded && <MyContent> }

Even though I "wait" for the actions to finish (= Promise.all), my variable hasLoaded is set to true before the fetched data is set. Can anybody help?

like image 841
phoebus Avatar asked Oct 16 '22 09:10

phoebus


1 Answers

The problem is you return a function NOT a promise.
This resolves immediately.

See working code sample

export const fetchData2 = dispatch => () => {
  dispatch({type: 'START_FETCH'})
  const p = [
    fetchDataSetOne(dispatch),
    fetchDataSetTwo(dispatch)
  ];
  Promise.all(p).then((res) => setHasLoaded(res));
};

// this returns a promise AFTER it calls an action
const fetchDataSetOne = dispatch => {
  return axois.get(`${API_URL}/dataSetOne`).then(res => {
    dispatch({
      type: "FETCH_ALL_DATA_SET_ONE",
      payload: res.data.docs
    });
  });
};

This resolves after both promises are resolved, but the state updates after each promise is resolved. To update state after all promises resolve, try this:

export const fetchData3 = dispatch => () => {
  dispatch({ type: "START_FETCH" });
  const p = [
    axois.get(`${API_URL}/dataSetOne`),
    axois.get(`${API_URL}/dataSetTwo`)
  ];
  Promise.all(p).then(callActions(dispatch));
};

const callActions = dispatch => res => {
  dispatch({
    type: "FETCH_ALL_DATA_SET_ONE",
    payload: res[0].data.docs
  });
  dispatch({
    type: "FETCH_ALL_DATA_SET_TWO",
    payload: res[1].data.docs
  });
  setHasLoaded(res);
};
like image 90
Mke Spa Guy Avatar answered Oct 23 '22 13:10

Mke Spa Guy