Generators for reducer and action in Redux

Why Generators?

  • Very DRY, Don’t-Repeat-Yourself, reducer. Very minimal code in your reducer file.
  • Readable reducer code
  • Focus only to things that matter

Actions

Actions are plain JavaScript objects. Actions must have a type property that indicates the type of action being performed.

Typically when we use actions we write basic boilerplate with type and additional params. So our code looks like something this-

const LOGIN = ‘LOGIN’; 
{ 
type: LOGIN, 
text: ‘Login Redux app’ 
}

If we have a couple of actions then it makes sense to write the basic boilerplate.

But in real-world application, each API has certain states which we want to track. Generally, we have REQUEST, SUCCESS And ERROR states (In some cases RESET). So our action definition for a single API call looks like something –

enum Login {
REQUEST = ‘LOGIN_REQUEST’,
SUCCESS = ‘LOGIN_SUCCESS’,
ERROR = ‘LOGIN_ERROR’
}
export interface LoginRequest extends Redux.Action {
type: Login.REQUEST;
}
export interface LoginSuccess extends Redux.Action {
type: Login.SUCCESS;
data: any;
}
export interface LoginError extends Redux.Action {
type: Login.ERROR;
error: any;
}

When you have hundreds of actions then it makes it difficult to write those down.

What we have here:

  • We are repeating ourselves a lot.
  • Growing Bundling size.
  • Unfocussed work.

So what we do now? What about creating an action generator?

Reducers

Similar to the action we write reducers corresponding to actions. In general, we have reducer handler for REQUEST, SUCCESS, and ERROR states, which typically looks like –

export function Login(state: ILoginState = defaultState, action: TLoginAction) {
switch (action.type) {
case actions.LoginAction.REQUEST:
return Object.assign({}, state, {
asyncStatus: AsyncStatus.LOADING
});
case actions.LoginAction.SUCCESS:
return Object.assign({}, state, action[‘data’], {
asyncStatus: AsyncStatus.SUCCESS
});
case actions.LoginAction.ERROR:
return Object.assign({}, state, {
asyncStatus: AsyncStatus.ERROR
});
default:
return state;
}
}

Similar to actions we are also repeating ourselves a lot.

Generator Implementation

Action Generators

For API actions we can write a generic action interface with fields type(required), and data and error as optional attributes.

export interface Action<T, D = {}, E = {}> extends Redux.Action {
type: T
data?: D
error?: E
}

We can use it directly as –

dispatch<Action<Validate2faAction.REQUEST>>({ type: Validate2faAction.REQUEST });

Reducer Generators

Similarly, in the case of reducers, we can write a generic function createReducer, which will create generic reducer with common states (REQUEST, SUCCESS, and ERROR) handling. (Note: we are already using it in desktop in some reducers).

export function createReducer<IState>(
 requestAction: any,
 successAction: any,
 errorAction: any,
 defaultState: IState
) {
return function (state: IState = defaultState, action: IAction = { 
 type: null }): IState {
 switch (action.type) {
  case requestAction:
   return Object.assign({}, state, {
   asyncStatus: LOAD
  });
  case successAction:
   return Object.assign(
    {},
   state,
   {
   asyncStatus: SUCCESS
  },
  action.data
);
case errorAction:
  return Object.assign(
  {},
  state,
  {
   asyncStatus: ERROR
 },
  action.error
);
 default:
  return state;
 }
 };
}

Conclusion

Create your own generated function for actions and reducer is a must.

I recommend you to read Redux documentation about reducing boilerplate to grasp the concept and how the generated function reducer should works. After that create your own generated function reducer and take the advantage.

We here at HYR Global Source have a very deep understanding of web development growing process, In the last 5 years, we have worked with various clients and students, and helped them in creating better products and careers respectively. 

In HYR Global Source, We have dedicated mentorship programs for students and software professionals to get into the world of web development. If it is something which interests you please connect us here – https://www.hyrglobalsource.com/contact.html

If you already well versed in technology, then we are always looking for bright minds like you, Please check out career page here – https://www.hyrglobalsource.com/careers.html

Leave a Reply

Your email address will not be published. Required fields are marked *