Reduce redux reducer boilerplate for http request

There are similar things that I want to do for each http call

  1. before request I want to show loader for every http call
  2. hide the loader after it’s finished
  3. if error stop the loader and show the error msg

I’m using redux thunk, to do that I have to copy and paste big chunk of code

export function userReducer(state = {
  signup_loading: false,
  signup_failed: '',
  signup_error: '',
  login_loading: false,
  login_failed: '',
  login_error: ''
}, { payload, payload: { data, error } }) {
  switch (action.type) {
    case SIGNUP_REQUEST:
      return {
        signup_loading: true
      }
    case SIGNUP_SUCCESS:
      return {
        signup_loading: false,
        data
      }
    case SIGNUP_FAILED:
      return {
        signup_loading: false,
        signup_error: error
      }
    case LOGIN_REQUEST:
      return {
        login_loading: true
      }
    case LOGIN_SUCESS:
      return {
        login_loading: false,
        data
      }
    case LOGIN_FAILED:
      return {
        login_loading: false,
        login_error: error
      }
    default: return state
  }
}

How can I reduce this?

Ah, few days ago I was thinking about a similar question; unfortunately I didn’t find the answer :confused:
You can simplify the code making the structure of your project more … structured!

I mean, the default state is something you can take out of there ( using a const init just to make the code more readable) , as well as the login/signup processes that you can separate in your reducer and combine them after: this will lead to a more nested state structure, I still can’t figure it out which one is better or included in best practice.
This is what my signup reducer looks like:

export const signupState = (state = {}, action) => {
    switch(action.type) {
        case registerProcess.REQUEST:
            return {};
        case registerProcess.SUCCESS:
            return action.newUser;
        case registerProcess.FAILURE:
            return action.err;
        default: 
            return state;
    }
};

Here is the actions. imported at the top of the user reducer file:

export const registerProcess = {
    REQUEST:"REGISTER_REQUEST",
    SUCCESS:"REGISTER_SUCCESS",
    FAILURE:"REGISTER_FAILED"
};

If you will then join this one with the login one and at the end of the day you will retrieve it writing something like:
state.userState.signupState

  • if you can have a single set of operations for any http request, then you should do that - even if that is just hooking into the error response. eg: you delegate to a fetch operation which will either update the state with an error message, or stuff will pass on through and load. In that case it should be irrelevant what the operation is: if you trigger an http request, state somewhere will be set to loading, then state somewhere will be set to error/success
  • If it isn’t possible to do that, then you should be handling it explicitly, and how it is at the minute would be correct whatever language/framework you were using. If all the actions have genuinely different consequences, then copy paste, don’t attempt to abstract.

it doesn’t reducer the amount of code I have to write, what you did was just created 2 separated files.

There’s no different consequences for ${action}_REQUEST and ${action}_FAILURE because the app will show loading at request, and stop the loading at failure, no matter what action it is.

Well, this is what I’m saying: if they’re exactly the same, you don’t need “login state” or “sign-up state”, you just need a generic “stuff that happens when an HTTP request succeeds
/fails state”

There’s no different consequences for ${action}_REQUEST and ${action}_FAILURE

Mh :confused:
I’m not getting something here: the request will send nothing back, is just a flag to indicate that the fetch is in progress; on the other hand if the request will fail you will have a fail message, you want to store it around to display it and/or do something in reaction of it.
I always thought that that was the point having three different states for each request.

if you can have a single set of operations for any http request

if they’re exactly the same, you don’t need “login state” or “sign-up state”,

About this: ‘loading’ state apart, is this viable? I mean, to have a single set of operation would need some more code to address the results am i wrong? Different sections of code designed to display different kind of errors / data in different moments would have to refer to the same state so you will need to solve this adding some code elsewhere right?

I was thinking about a similar question; unfortunately I didn’t find the answer :confused:
you can simplify the code (…)