React Checkbox Component Unchecking Issue - All Checkboxes Cleared and Array Refilled on Slide Change

61 views Asked by At

I'm encountering a perplexing issue in a React application where I have implemented a set of checkboxes. The initial state is such that all checkboxes are selected by default. However, when I uncheck any checkbox, it seems to clear all the checkboxes and retain only the unchecked one. Additionally, upon moving to the next slide and returning, the array holding the selected checkbox values is refilled with all the default values.

import React from "react";
import { Checkbox } from "@carbon/react";

const CheckBoxInput = ({
  item,
  data,
  setSelectedCheckboxValues,
  selectedCheckboxValues,
}) => {
  const [isChecked, setIsChecked] = React.useState(true);

  React.useEffect(() => {
    setIsChecked(selectedCheckboxValues.includes(item.title));
  }, [selectedCheckboxValues, item.title]);

  const handleCheckBoxChange = React.useCallback(
    (event, { checked, id }) => {
      const updatedValues = selectedCheckboxValues.includes(id)
        ? selectedCheckboxValues.filter((val) => val !== id)
        : [...selectedCheckboxValues, id];
      setSelectedCheckboxValues(updatedValues);
    },
    [selectedCheckboxValues, setSelectedCheckboxValues]
  );

  return (
    <>
      <Checkbox
        onChange={handleCheckBoxChange}
        labelText={item.title}
        id={item.title}
        defaultChecked={isChecked}
      />
    </>
  );
};

export default CheckBoxInput;




Issue:

  1. Unchecking a checkbox results in clearing all checkboxes, keeping only the one that is unchecked.
  2. Moving to the next slide and returning refills the selectedCheckboxValues array with all default values.

Sandbox link with the problem

Expected Behavior:

  1. Unchecking a checkbox should update the array, keeping the other checkboxes in their current state.
  2. Moving between slides should not affect the state of the checkboxes or the selectedCheckboxValues array.

Any assistance or guidance on resolving this issue would be greatly appreciated.

Update

Adding the items to the array on component mount (useEffect with empty dependency array) did the thing.

Slides.js

React.useEffect(() => {
    if (slides[currentSlide]?.content) {
      const allCheckboxValues = slides[currentSlide].content.map(
        (item) => item.title
      );
      setSelectedCheckboxValues(allCheckboxValues);
    }
  }, []);

But then I figured out that when I swap the position of content array from first element to any other position, it will stop working again.

Same code in another sandbox with the difference that content array is not in the first object of the slides array: Sandbox Link

New Array

const SLIDES = [
  {
    title: "Checkboxes",
    text: "We're gonna do 3 fundamental exercises.",
  },
  {
    title: "First, 10 push-ups",
    text: "Do 10 reps. Remember about full range of motion. Don't rush.",
    content: [
      {
        title: "Test1",
      },
      {
        title: "Test2",
      },
      {
        title: "Test3",
      },
      {
        title: "Test4",
      },
      {
        title: "Test5",
      },
    ],
...rest of the elements
  },
];

Any ideas?

2

There are 2 answers

0
FD3 On BEST ANSWER

The easiest way so solve the Problem was to add the array of checkbox values on the initialization of the state which is responsible for holding the checked checkbox values and it works fine.
Sandbox link

  const content = ["Test1", "Test2", "Test3", "Test4", "Test5"];
  const [selectedCheckboxValues, setSelectedCheckboxValues] =
    React.useState(content);
1
Nacho On

The problem seems to be that the isChecked state is not being updated correctly when a checkbox is unchecked, and this is causing undesired behavior.

To fix this issue, you can directly use the isChecked state to determine the checked state of the checkbox instead of relying on defaultChecked

import React from "react";
import { Checkbox } from "@carbon/react";

const CheckBoxInput = ({
  item,
  selectedCheckboxValues,
  setSelectedCheckboxValues,
}) => {
  const isChecked = selectedCheckboxValues.includes(item.title);

  const handleCheckBoxChange = (event, { id }) => {
    const updatedValues = selectedCheckboxValues.includes(id)
      ? selectedCheckboxValues.filter((val) => val !== id)
      : [...selectedCheckboxValues, id];
    setSelectedCheckboxValues(updatedValues);
  };

  return (
    <>
      <Checkbox
        onChange={handleCheckBoxChange}
        labelText={item.title}
        id={item.title}
        checked={isChecked}
      />
    </>
  );
};

export default CheckBoxInput;