You can make thunk action creator as Promise, make easier to control async jobs.
export function createXHRAction(xhrType, dispatch, options) { // you can customize createXHRAction here with options parameter. dispatch({ type: xhrType, data: { fetching: true, data: [] }); return new Promise( (resolve, reject) => { fetch(options.url, { ... }) .then( (response) => { // to getting server response, you must use .json() method and this is promise object let parseJSONPromise = response.json(); if(response.status >= 200 && response.status < 300) { parseJSONPromise.then( (result) => { dispatch({ type: xhrType, data: { fetching: false, data: result.data }); resolve(result.data); }); return parseJSONPromise; // make possible to use then where calling this } else { return parseJSONPromise.then( res => { reject({ message: res.error.message }); }); } }) .catch( (error) => { // handles common XHR error here }); }); }
now you can easily create new XHR actions like this:
import { createXHRAction } from './actions'; export function getUser(id) { return (dispatch) => { return createXHRAction('user', dispatch, { method: 'get', url: `/user/${id}` }); }; }
now you can use thunk action like synchronous:
import { dispatch } from './store'; import { getUser } from './action/user'; class SomeComponent extends React.Component { ... loadData(id) { // from here, store's state should be { fetching: true, data: [] } dispatch(getUser(id)) .then( (userData) => { // now from here, you can get the value from parameter or you can get it from store or component props if super component passing it by redux provider. // store state should be { fetching: false: data [..., ...] } // do something with received data }) .catch( (error) => { })); } }