Hello react developer,
In this react redux reducer best practice and react redux action best practice example tutorial, I will discuss and show you how we can write our reducer and actions in a good way to maintain our application state and errors.
You know that when we write our reducer we are to maintain our state in a good way. You know that in redux, a reducer is a pure function that takes an action and the previous state of the application and returns the new state.
So if you write your reducer in a good way, then it is very easy to handle errors and state in your react redux application. So i am here to share with you that how i am writting my reducer and actions in my react redux application.
Assume we need to maintain our category state. So what I did to handle this? Firstly I create a different types like:
export enum CategoryTypes {
CATEGORY_ACTION_START = "CATEGORY_ACTION_START",
CATEGORY_GET_SUCCESS = "CATEGORY_GET_SUCCESS",
CATEGORY_GET_FAILED = "CATEGORY_GET_FAILED",
CATEGORY_CREATE_SUCCESS = "CATEGORY_CREATE_SUCCESS",
CATEGORY_CREATE_FAILED = "CATEGORY_CREATE_FAILED",
CATEGORY_GET_BY_ID_SUCCESS = "CATEGORY_GET_BY_ID_SUCCESS",
CATEGORY_GET_BY_ID_FAILED = "CATEGORY_GET_BY_ID_FAILED",
CATEGORY_UPDATE_SUCCESS = "CATEGORY_UPDATE_SUCCESS",
CATEGORY_UPDATE_FAILED = "CATEGORY_UPDATE_FAILED",
CATEGORY_ACTION_END = "CATEGORY_ACTION_END",
}
Then having created this types, I write my reducer like that,
import { CategoryTypes } from "./category.types";
const INITIAL_STATE = {
data: "",
error: "",
loading: false,
};
const categoryReducer = (state = INITIAL_STATE, action: any) => {
switch (action.type) {
case CategoryTypes.CATEGORY_ACTION_START:
return {
...state,
loading: true,
};
case CategoryTypes.CATEGORY_GET_SUCCESS:
return {
...state,
data: action.payload,
error: "",
};
case CategoryTypes.CATEGORY_GET_FAILED:
return {
...state,
error: action.payload,
};
case CategoryTypes.CATEGORY_CREATE_SUCCESS:
return {
...state,
data: action.payload,
error: "",
};
case CategoryTypes.CATEGORY_CREATE_FAILED:
return {
...state,
error: action.payload,
};
case CategoryTypes.CATEGORY_UPDATE_SUCCESS:
return {
...state,
data: action.payload,
error: "",
};
case CategoryTypes.CATEGORY_UPDATE_FAILED:
return {
...state,
error: action.payload,
};
case CategoryTypes.CATEGORY_GET_BY_ID_SUCCESS:
return {
...state,
data: action.payload,
};
case CategoryTypes.CATEGORY_GET_BY_ID_FAILED:
return {
...state,
error: action.payload,
};
case CategoryTypes.CATEGORY_ACTION_END:
return {
...state,
loading: false,
};
default:
return state;
}
};
export default categoryReducer;
This is the way, I write my reducer to handle state and issues related to this state. Then I write my every action like below:
import { AxiosAuthInstance } from "../../../../config/api/auth.axios";
import { store } from "../../../../config/redux/store";
import { snackBarAlert } from "../../../../redux/alert/alert.action";
import { CategoryTypes } from "./category.types";
export const categoryGetAction = () => async (dispatch: any) => {
dispatch({
type: CategoryTypes.CATEGORY_ACTION_START,
});
await AxiosAuthInstance.get("/category").then(
(res: any) => {
dispatch({
type: CategoryTypes.CATEGORY_GET_SUCCESS,
payload: res?.data,
});
dispatch({
type: CategoryTypes.CATEGORY_ACTION_END,
});
},
(error: any) => {
dispatch({
type: CategoryTypes.CATEGORY_GET_FAILED,
payload: error,
});
dispatch({
type: CategoryTypes.CATEGORY_ACTION_END,
});
}
);
};
export const categoryCreateAction = (formDate: any) => async (
dispatch: any
) => {
dispatch({
type: CategoryTypes.CATEGORY_ACTION_START,
});
await AxiosAuthInstance.post("/category", formDate).then(
(res: any) => {
dispatch({
type: CategoryTypes.CATEGORY_CREATE_SUCCESS,
payload: res?.data,
});
dispatch({
type: CategoryTypes.CATEGORY_ACTION_END,
});
//! bad solution start
localStorage.removeItem("error");
//! bad solution end
store.dispatch(
snackBarAlert(
res?.data?.message,
"success",
CategoryTypes.CATEGORY_CREATE_SUCCESS
)
);
},
(error: any) => {
dispatch({
type: CategoryTypes.CATEGORY_CREATE_FAILED,
payload: true,
});
dispatch({
type: CategoryTypes.CATEGORY_ACTION_END,
});
//! bad solution start
localStorage.setItem("error", error);
//! bad solution end
store.dispatch(
snackBarAlert(
error?.response?.data?.error,
"danger",
CategoryTypes.CATEGORY_CREATE_FAILED
)
);
}
);
};
export const categoryGetByIdAction = (id: any) => async (dispatch: any) => {
dispatch({
type: CategoryTypes.CATEGORY_ACTION_START,
});
await AxiosAuthInstance.get(`/category/${id}`).then(
(res: any) => {
dispatch({
type: CategoryTypes.CATEGORY_GET_BY_ID_SUCCESS,
payload: res?.data,
});
dispatch({
type: CategoryTypes.CATEGORY_ACTION_END,
});
},
(error: any) => {
dispatch({
type: CategoryTypes.CATEGORY_GET_BY_ID_FAILED,
payload: error,
});
dispatch({
type: CategoryTypes.CATEGORY_ACTION_END,
});
}
);
};
export const categoryUpdateAction = (id: any, formData: any) => async (
dispatch: any
) => {
dispatch({
type: CategoryTypes.CATEGORY_ACTION_START,
});
await AxiosAuthInstance.put(`/category/${id}`, formData).then(
(res: any) => {
dispatch({
type: CategoryTypes.CATEGORY_UPDATE_SUCCESS,
payload: res?.data,
});
dispatch({
type: CategoryTypes.CATEGORY_ACTION_END,
});
//! bad solution start
localStorage.removeItem("error");
//! bad solution end
store.dispatch(
snackBarAlert(
res?.data?.message,
"success",
CategoryTypes.CATEGORY_UPDATE_SUCCESS
)
);
},
(error: any) => {
dispatch({
type: CategoryTypes.CATEGORY_UPDATE_FAILED,
payload: true,
});
dispatch({
type: CategoryTypes.CATEGORY_ACTION_END,
});
//! bad solution start
localStorage.setItem("error", error);
//! bad solution end
store.dispatch(
snackBarAlert(
error?.response?.data?.error,
"danger",
CategoryTypes.CATEGORY_UPDATE_FAILED
)
);
}
);
};
Recommended: React Redux Complete Setup Example with Api Call
Hope it can help you.
#react-js