Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux-Thunk Chaining Actions, getting a "dispatch(...) then is not a function error

In order for me to set the Composition, I have to get the Output object first.
I'm trying to copy the examples and I feel like I'm copying the syntax correctly but I keep getting the error:

Uncaught TypeError: dispatch(...).then is not a function

Actions.js

export function setComposition(composition) {
  return { type: types.SET_COMPOSITION, composition };
}

export function setOutputs(outputs) {
  return { type: types.SET_OUTPUTS, outputs };
}

export function setOutputsAndComposition(outputs) {
  return function (dispatch, getState) {
    return dispatch(setOutputs(outputs)).then(() =>  // ERROR HERE
      dispatch(setComposition(getState().Data.OutputObj))
    );
  }
}

EDIT: Ideally I would love to just create a function that just does this:

export function setOutputsAndComposition(outputs) {
  return function (dispatch, getState) {
    dispatch(setOutputs(outputs)).then(() =>
    dispatch(setComposition(getState().Data.OutputObj))
    );
  }
}

But somewhere I'm obviously not doing the syntax correctly

like image 620
user1189352 Avatar asked Jul 21 '17 18:07

user1189352


People also ask

How does a thunk have access to dispatch?

Where does this new dispatch argument come from? The short answer is that the redux-thunk middleware has access to the store, and can therefore pass in the store's dispatch and getState when invoking the thunk. The middleware itself is responsible for injecting those dependencies into the thunk.

What is Dispatch in Redux thunk?

Redux Thunk is a middleware that lets you call action creators that return a function instead of an action object. That function receives the store's dispatch method, which is then used to dispatch regular synchronous actions inside the function's body once the asynchronous operations have been completed.

What is getState in Redux thunk?

If you pass a function into dispatch , the thunk middleware sees that it's a function instead of an action object, intercepts it, and calls that function with (dispatch, getState) as its arguments. If it's a normal action object (or anything else), it's forwarded to the next middleware in the chain.

Is Redux thunk async?

As it turns out, Redux already has an official version of that "async function middleware", called the Redux "Thunk" middleware. The thunk middleware allows us to write functions that get dispatch and getState as arguments.


2 Answers

setOutputs() is returning a plain action object, and thus is not a thunk that returns a promise. So, chaining dispatch(setOutputs(outputs)).then() won't work.

If you just want to dispatch another action right after the setOutputs() dispatch is complete, you only need to put them right after each other:

dispatch(setOutputs(outputs));
dispatch(setComposition(getState().Data.OutputObj));
like image 96
markerikson Avatar answered Sep 25 '22 17:09

markerikson


You can use setOutputs() as a custom middleware. In this case I'm using it as a Promise instead:

export function setComposition(composition) {
  return { type: types.SET_COMPOSITION, composition };
}

export function setOutputs(outputs, dispatch) {
  return new Promise((resolve, reject) => {
    dispatch({type: types.SET_OUTPUTS, outputs});
    resolve();
  });
}

export function setOutputsAndComposition(outputs) {
  return function (dispatch, getState) {
    return setOutputs(outputs, dispatch).then(() =>  // NO ERROR HERE ANYMORE ^_^
      dispatch(setComposition(getState().Data.OutputObj))
    );
  }
}
like image 31
Lucaci Sergiu Avatar answered Sep 26 '22 17:09

Lucaci Sergiu