React Redux Reducer and Actions Best Practice Example

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. 

 

Facebook Github
A web enthusiastic, a self-motivated full-stack software engineer from Dhaka, Bangladesh with experience in developing applications using Laravel , React and Vue js