Checkbox List in React JS with Example

In this article, you will learn how to create a list of items with input checkboxes using React JS. We build the list using controlled input checkbox input with React state.

Here we will consider an example of the checklist of items where users can check/uncheck items through the input checkbox. The list of functionalities are as follows:

  1. Display the list of items on the screen.
  2. Check an item through the checkbox.
  3. Uncheck an item through the checkbox.
  4. Display text with a checked item that updates dynamically.
checkbox list in react
List of items with checkbox using React JS

1. Display list of items using Array.map()

The first step is to declare the list of the item names as an array of strings. Next, we will apply Array.map() on the checkList constant and return the JSX code with the item name in the callback function.

const checkList = ["Apple", "Banana", "Tea", "Coffee"];

return (
  <div className="checkList">
    <div className="title">Your CheckList:</div>
    <div className="list-container">
      {checkList.map((item, index) => (
         <div key={index}>
           <span>{item}</span>
         </div>
      ))}
    </div>
  </div>
);

2. Add input checkbox for every item

In order to add a checkbox for every item, we will include the HTML input of type=”checkbox” in the JSX code returned by the callback function of Array.map().

{checkList.map((item, index) => (
   <div key={index}>
     <input value={item} type="checkbox" />
     <span>{item}</span>
   </div>
))}

3. React State to track checked items

React State is declared to maintain the list of all checked items. The code is dynamically updated whenever “setChecked()” is called with the updated list as a parameter.

const [checked, setChecked] = useState([]);

4. Add and remove item from checked list

We will create a JS function to update the array based on the checkbox input with the following steps:

  1. Create JS variable with a copy of the checked React state.
  2. If the item is checked, a concatenated array of the existing array of items with the checked item.
  3. IIf the item is unchecked, the item is removed from the index using Array.splice().
  4. Call setChecked() with updated array value.
// Add/Remove checked item from list
const handleCheck = (event) => {
  var updatedList = [...checked];
  if (event.target.checked) {
    updatedList = [...checked, event.target.value];
  } else {
    updatedList.splice(checked.indexOf(event.target.value), 1);
  }
  setChecked(updatedList);
};

Next, we add the function to trigger for the onChange of checkbox input element.

<input value={item} type="checkbox" onChange={handleCheck} />

Learn more about Array.splice() from developer.mozilla.org/JavaScript/Array/splice.

5. Strikethrough text for checked items

We will assign different classNames for checked and unchecked items. We declare a JS function that returns string value based on whether the item is included in the checked array.

// Return classes based on whether item is checked
const isChecked = (item) =>
   checked.includes(item) ? "checked-item" : "not-checked-item";

Next, we will use the isChecked() function to determine the className of the <span></span> containing the item name.

<span className={isChecked(item)}>{item}</span>

We will add a strike-through text effect by including CSS styles for className “checked-item” in styles.css.

.checked-item {
  text-decoration: line-through;
}

6. Generate string with checked item names

The checkedItems() JS function is declared to generate a string of checked items in the format of “item1, item2, item3, …” or return an empty string if no items are checked.

// Generate string of checked items
var checkedItems = checked.length
    ? checked.reduce((total, item) => {
        return total + ", " + item;
      })
    : "";

7. Display the checked item names

Finally, to display the string of checked items, we will include checkedItems variable in the JSX code returned by the App component.

<div>
  {`Items checked are: ${checkedItems}`}
</div>

Final Solution Code

App.js

import React, { useState } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  // State with list of all checked item
  const [checked, setChecked] = useState([]);
  const checkList = ["Apple", "Banana", "Tea", "Coffee"];

  // Add/Remove checked item from list
  const handleCheck = (event) => {
    var updatedList = [...checked];
    if (event.target.checked) {
      updatedList = [...checked, event.target.value];
    } else {
      updatedList.splice(checked.indexOf(event.target.value), 1);
    }
    setChecked(updatedList);
  };

  // Generate string of checked items
  const checkedItems = checked.length
    ? checked.reduce((total, item) => {
        return total + ", " + item;
      })
    : "";

  // Return classes based on whether item is checked
  var isChecked = (item) =>
    checked.includes(item) ? "checked-item" : "not-checked-item";

  return (
    <div className="app">
      <div className="checkList">
        <div className="title">Your CheckList:</div>
        <div className="list-container">
          {checkList.map((item, index) => (
            <div key={index}>
              <input value={item} type="checkbox" onChange={handleCheck} />
              <span className={isChecked(item)}>{item}</span>
            </div>
          ))}
        </div>
      </div>

      <div>
        {`Items checked are: ${checkedItems}`}
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

styles.css

.app {
  font-family: sans-serif;
  font-size: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 20px;
  height: 100vh;
  font-family: Cambria, Cochin, Georgia, Times, "Times New Roman", serif;
}
.title {
  font-size: 22px;
  margin-bottom: 10px;
}
.list-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-left: 20px;
}
.checked-item,
.not-checked-item {
  margin-left: 10px;
}
.checked-item {
  text-decoration: line-through;
}