1
votes

I am new to redux. So after reading lots of tutorials.I understood that, redux need redux thunk to dispatch async actions by returning another function.But if I call http request inside custom middle-ware then

  1. is it required redux thunk ?
  2. is Redux custom middleware no side effects ? I mean no need to return another function.

If i use redux thunk then my action creator looks like this. This I understood

function incrementAsync() {
  return (dispatch) => {
    setTimeout(() => {
      // Yay! Can invoke sync or async actions with `dispatch`
      dispatch(increment());
    }, 1000);
  };
}

I have confusion in custom middle-ware.

https://blog.logrocket.com/managing-asynchronous-actions-in-redux-1bc7d28a00c6/

as per this blog

const httpMiddleware = store => next => action => {
  if (action[HTTP_ACTION]) {
    const actionInfo = action[HTTP_ACTION];
    const fetchOptions = {
      method: actionInfo.verb,
      headers: actionInfo.headers,
      body: actionInfo.payload || null
    };

    next({
      type: actionInfo.type + "_REQUESTED"
    });

    fetch(actionInfo.endpoint, fetchOptions)
      .then(response => response.json())
      .then(data => next({
        type: actionInfo.type + "_RECEIVED",
        payload: data
      }))
      .catch(error => next({
        type: actionInfo.type + "_FAILED",
        payload: error
     }));
  } else {
    return next(action);
  }
}

they are not returning any dispatch function inside action. I know that store,next,action are the inner functions.

can any one help me to understand about this?
Thank you.

2

2 Answers

3
votes

All redux-thunk is is a simple redux middleware that checks if your action is a function and acts accordingly. You can build it yourself in 5 minutes.

You can see that it deconstructs dispatch and getState from the store object, and then calls your action with them as parameters.

Have a look at it's source code.

So, your example code can look like this:

const httpMiddleware = store => next => action => {
  if (action[HTTP_ACTION]) {
    const actionInfo = action[HTTP_ACTION];
    const fetchOptions = {
      method: actionInfo.verb,
      headers: actionInfo.headers,
      body: actionInfo.payload || null
    };

    store.dispatch({
      type: actionInfo.type + "_REQUESTED"
    });

    fetch(actionInfo.endpoint, fetchOptions)
      .then(response => response.json())
      .then(data => store.dispatch({
        type: actionInfo.type + "_RECEIVED",
        payload: data
      }))
      .catch(error => store.dispatch({
        type: actionInfo.type + "_FAILED",
        payload: error
     }));
  } else {
    return next(action);
  }
}
2
votes

As you asked by point list I'm gonna reply by point list:

  • If i call http request inside custom middleware then is it required redux thunk ?

Redux thunk is a middleware per se, it's recommended if you want to dispatch an action that make (let's say, for example) an AJAX call and dispatch two different action based on the result of that AJAX call, one if it fails and one if it succeeds.

  • is Redux custom middleware no side effects ? i mean no need to return another function.

If I'm understanding correctly: A middleware will simply take the action you dispatched and pass it through the chain, it'll let you do something before sending the action to the reducer "phase". What it'll do is entirely up to you. You need at least to do next(action) or block the action based on some logic, if needed.

Finally, a custom middleware like the one you posted is modifying the action you passed based on the response of an AJAX call, making it more of an "interceptor" than a simple middleware. Written this way, it's not dispatching a new action, it's more related to modifying the action you passed.

If you want to dispatch a new action based on the result of an ajax call, but without creating a middleware/interceptor, you could do it this way:

const postSomethingAction = postObject => {
    return async dispatch => {
        dispatch(postSomethingPending())
        const response = await Api.postSomething(postObject)
        if (response.message) {
            dispatch(postSomethingError(response))
        }
        else {
            dispatch(postSomethingSuccess(response.data))
        }
    }
}

In this example we're using Thunk do create an action that dispatch another action based on the result of Api.postSomething