Chaim Friedman
Chaim Friedman

Reputation: 6253

Why do redux-thunks need to be bound to dispatch?

I think I am missing a fundamental piece of understanding here. I am aware that in order for an action to be created and thus set off the redux chain of events, the action creator must be invoked using dispatch.

However, when we have a redux-thunk which returns a function which will call dispatch on our action creator, why must the redux-thunk also be called with dispatch?

For example take the following redux-thunk:

function savePerson(person: Person) {
    return async (dispatch: any) => {
        delete person.cars;
        let newPerson = await axios.post('/api/people/addPeron', person);
        dispatch(addPersonSuccess(person));
    }
}

Calling this savePerson function without dispatch does not set off the redux flow, and I don't understand why considering the function it returns calls our action creator with dispatch. Can anybody clarify what I seem to be missing here?

Upvotes: 4

Views: 320

Answers (1)

Mario Tacke
Mario Tacke

Reputation: 5488

All redux middleware follows the same general layout:

const middleware => store => next => action => next(action);

Why must the redux-thunk also be called with dispatch?

Like you correctly pointed out in your first paragraph, for an action/thunk to be evaluated by the redux middleware chain, it must be dispatched by the calling code.

I think the misunderstanding comes in here:

"...when we have a redux-thunk which returns a function which will call dispatch on our action creator...".

While it is correct that the returned function dispatches an action, it is only half the story. Technically, you are dispatching twice: first savePerson and later addPersonSuccess. The former being a thunk and the latter, most likely, being a plain action.

Now, let's consider the current redux-thunk source code:

function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

...

export default thunk;

Once you dispatch savePerson, the middleware recognizes your action as a function. It then injects dispatch as the first argument to later allow dispatching of other actions. Up until now, dispatch has not been invoked on your addPersonSuccess action. Only after your asynchronous call to add a person will the dispatch be called on addPersonSuccess.

I like to think of this as passing the redux context along in the thunk (dispatch, getState, etc).

References

Upvotes: 2

Related Questions