Create reusable checkbox component in reactjs and store state in redux?

A reusable checkbox component can help you in displaying custom checkbox in your project at multiple places. This will speedup your process of creating checkboxes multiple times throughout application design.

The main issue which people face while creating a reusable component is to how to store the data. Because you will need a central state management system for that.

Also, you will need to identify the different checkboxes in your application uniquely. Since the reusable component is going to be used multiple times, then how will we know what value belongs to which component? That’s why we need id.

In this article we will show you the complete reactjs code of reusable checkbox component. To store checked/unchecked states, we will use redux.

Step1: Installing Redux and React-Redux

If you have already installed redux and react-redux packages, then you may skip this step. If you are unfamiliar with the workings of redux, then I will recommend you to read quick step by step redux.

Use this command to install both redux and react-redux. Remember, to run this command from inside your project directory.

npm install redux react-redux

# Using Yarn

yarn add redux react-redux

Step 2: Creating Reusable Checkbox Component

A reusable checkbox component will comprise of Checkbox JSX and Redux state. In this step we will only create the Checkbox JSX. While we will connect the redux to it in the next step.

Let’s call this file, CustomCheckbox.js. Here is the code –

import React from "react";

const CustomCheckbox = (props) => {
  
  return (
    <>
      <input
        type="checkbox"
        {...props}
      />
      {props.text}
    </>
  );
};

export default CustomCheckbox;

There are few important points about this component –

Step 3: Adding Redux to the project

To add redux, we need these files and directories –

  1. Store
  2. Reducers
  3. Composite Reducer

The directory structure will be like this –

project
|- src
   |- reducers
   |   |- CustomCheckboxReducer.js
   |   |_ index.js
   |- store.js
   |- index.js
   |_ app.js
reusable checkbox component with redux directory structure

Let’s create all the files needed for redux.

store.js

import { createStore } from "redux";
import rootReducer from "./reducers/index";
const store = createStore(rootReducer);
export default store;

reducers/CustomCheckboxReducer.js

/**
 This reducer file is for checkbox component
*/

// Initial state
const initialState = {
// checkboxes object will hold id and checkbox state
// of all custom checkboxes.
// It is required to have unique id for each checkbox
  checkboxes: {
    "0": false // id : checked state
  }
};

const reducer = (state = initialState, action) => {
// Condition will trigger for CHANGE_CHECKBOX event
  if (action.type === "CHANGE_CHECKBOX") {
    return {
      ...state,
      checkboxes: {
        ...state.checkboxes,
        [action.payload.checkBoxId]: action.payload.checkBoxState
// In payload we will pass checkbox id and checkbox state
      }
    };
  }
  return state;
};
export default reducer;

In this code we have provided comment for better understanding.

We will need another file to combine all the reducers. In this code we have only one reducer but in real world project there will be many. So, a file to combine them is required.

reducers/index.js

import { combineReducers } from "redux";
import CustomCheckboxReducer from "./CustomCheckboxReducer";

const rootReducer = combineReducers({
  CustomCheckboxReducer
});

export default rootReducer;

Step 4: Add redux store to index.js file

Redux won’t work till we add store to the high level component. Here we have index.js with top level component. So we will add store there.

index.js

import { createRoot } from "react-dom/client";

import App from "./App";

import { Provider } from "react-redux";

import store from "./store";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

Step 5: Adding Redux Support in Reusable Checkbox Component

Since our redux setup is already completed, so we are ready to add it in reusable checkbox component.

We will use two redux functions – useSelector() and useDispatch().

useSelector() is used for reading any state change in our application.

useDispatch() is used for performing a state change.

So, when a checkbox is checked, we use useDispatch() to change state from unchecked to checked. And then useSelector() will read this change throughout the application.

CustomCheckbox.js

import React from "react";
import { useSelector, useDispatch } from "react-redux";

const CustomCheckbox = (props) => {
  // Reading state of checkbox and 
  // storing in checkBoxState variable.

  // First check if checkbox id (props.checkBoxId)
  // already exists in CustomCheckboxReducer.js state
  // if not, then check if props.checkBoxState is set
  // if not, then choose false
  const checkBoxState = useSelector(
    (state) =>
      state.CustomCheckboxReducer.checkboxes[props.checkBoxId] ||
      props.checkBoxState ||
      false
  );

  const dispatch = useDispatch();

  return (
    <>
      <input
        type="checkbox"
        {...props} // set all props as attributes
 // set checked state according to checkBoxState variable
 // This variable satisfies the conditions of redux state
 // and default value supplied in checkbox
        checked={checkBoxState ? "checked" : ""}
        onChange={() => {
          dispatch({   // calling dispatch to change state
            type: "CHANGE_CHECKBOX",  // action matching in reducer
            payload: {
 // id need to be supplied as props when using this component
              checkBoxId: props.checkBoxId,
              checkBoxState: !checkBoxState
            }
          });
        }}
      />
      {props.text}
    </>
  );
};

export default CustomCheckbox;

Step 6: Use Custom Checkbox in Project

Now you can use this custom checkbox anywhere in your project. I will show you the functionality by using it in App.js file. But you can use it in any component.

App.js

import "./styles.css";
import CustomCheckbox from "./CustomCheckbox.js";
import { useSelector, useDispatch } from "react-redux";

export default function App() {
  const checkBoxState = useSelector((state) => state.CustomCheckboxReducer);

  return (
    <div>

      <CustomCheckbox
        name={"customCheck"}
        value={"ironman"}
        text={"I am Ironman"}
        checkBoxId={"checkbox_ironman"}
        checkBoxState={false}
      />{" "}

      <br />

      <CustomCheckbox
        value={"Captain America"}
        text={"I am Captain America"}
        checkBoxId={"checkbox_captain_america"}
        checkBoxState={false}
      />

      <p>Checkbox Info, fetched from reducers - </p>
      <pre>{JSON.stringify(checkBoxState, null, "\t")}</pre>
    </div>
  );
}

The output will look like this –

Reusable custom checkbox project output

Live Demo

Open Live Demo

Conclusion

Creating a reusable checkbox component is fairly easy and useful. Once created, you can use them anywhere in your project. If there are specific needs of UI designs and patterns of your organization, then apply those to your reusable checkbox once. Then you can get a consistent appearance everywhere.