1

I'm new to Redux and I have some confusing questions:

1. The official docs says when using middleware, each the middleware function can return other than new state object(next(action)), such as function or Promise(even without using redux-thunk). If this is the case, how can this callback or promise be later reached in the code? Just call it in chaining manner after dispatch(actionCreater)?

In the above situation, the function callback is returned rather than an object, then how is it handled through the chaining middlewares?

2. Kind of extension from 1st question, if there are more than 2 middlewares and several middlewares return callback instead of state, are these callbacks all available to use? I mean, to use them, just call it like dispatch(actionCreater).CALLBACK_NAME()?

If the callbacks have incidently the same name, how this can be handled?

cadenzah
  • 928
  • 3
  • 10
  • 23

3 Answers3

1

then how is it handled through the chaining middlewares?

I think the chaining is just stopped. For example, looking at redux-thunk's code, if an action is a function, the result of that function is returned, and next is not called; so all the following middlewares are not processing this action.

I think it's logical, because most of the middlewares expect action to be object instead of function. If this function-type action is passed along, those middlewares would broke.

how can this callback or promise be later reached in the code?

I think you have to handle it right away after calling dispatch, pretty much what you described "Just call it in chaining manner after dispatch(actionCreater)".

Like the redux-thunk example

dispatch(makeASandwichWithSecretSauce('My partner')).then(() => {
  console.log('Done!');
});

if there are more than 2 middlewares and several middlewares return callback instead of state, are these callbacks all available to use?

I think, the answer is "no". Because the chaining is stopped. If any special action is handled by a certain middleware, that action cannot be passed by calling next, otherwise the special action might break other normal middlewares.

So I guess there are several solutions:

  1. Only use one type of special middleware, so there won't be conflicts.

  2. If more than one special middleware, manually compose all these middlewares, make it a new middleware, then send the new one into redux applyMiddleware.

  3. Use some more generic/robust middleware that could handle complex async behavior, like redux-saga.

The idea of 2 maybe like this

const manually = store => next => action => {
  if (typeof action === 'function') {
    const promise = thunk(action);
    const promise2 = anotherThunk(action);

    // this is also tricky, because action is a function, you have to make a new object
    const whatToPass = {
      type: 'what is this', // depends on your need?
      // any other data?
    };
    next(whatToPass); // chaining goes on

    // maybe return this, but maybe not good,
    // because every promise needs to resolve to trigger the 'then'
    return Promise.all([
      promise,
      promise2,
    ]);
  }
  return next(action);
}
Marson Mao
  • 2,935
  • 6
  • 30
  • 45
  • Pretty much similar conclusion to what I understand so far. I think the fact that I can use `.then()` after `dispatch` and manage the flow with `resolve` and `reject` improves the async behavior. But as you mentioned, it would be nicer to use `redux-saga` to control in more sophisticated way. – cadenzah Apr 24 '20 at 00:42
  • Happy that we're having similar thoughts :D and yes I really like `redux-saga`, I feel it could write business logics in human readable flows, easy to maintain; and could isolate async/complex logics out of UI component, but this statement is case by case because sometimes you maybe just want to write all the logics inside a component, but if the logics is cross-components then saga is a good place. – Marson Mao Apr 24 '20 at 08:24
0

redux middleware give store as parameter of middleware, you can use that for getting state. You can use store.getState() for getting state. Middleware callbacks structure are as below....

const customMiddleware = store => next => action => {
   const result = next(action);
   console.log("State", store.getState());
   console.log("Action", action.type);
   return result;
}

where store is the redux store, next works same as store.dispatch, action is the action which currently executed.

Herat Patel
  • 779
  • 3
  • 10
0

I think this question pretty much asked a same kind of question I was encountered. And sadly, nothing clear answer exists yet.

cadenzah
  • 928
  • 3
  • 10
  • 23