6

As redux thunk calls functions returned by action creators asynchronously, how I can ensure after calling the action creator that redux has actually dispatched the action before moving on?

I need to fetch CSRF token before each POST request to server, and for both procedure there's an corresponding action.

The problem is, if I call those action creators successively, POST action is for some reason getting dispatched before CSRF action is dispatched. I want to keep these concerns separated, so I don't want to combine the actions.

How I can synchronize the action creator calling code with redux thunk dispatching those actions?

2 Answers 2

6

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) => { })); } } 
Sign up to request clarification or add additional context in comments.

Comments

2

You need to wait for CSRF-token request to finish before starting POST request.

I think it would be better to wrap all that code into action creator

function postAction(data) { fetchToken().then((token) => { //you have got token here and can use it for the POST-request. doPost(data, token).then(() => { //dispatch success action if you need so }) }) } 

1 Comment

While this is a constructive workaround, there are cases where it would be very helpful to dispatch actions in sequence as the poster asked. E.g. you are working with a complicated project with trusted legacy code in existing action creators that "just works" and it's preferable to call those without modifying or refactoring.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.