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