How can I save the text value of the checkbox on Firestore?

I have this error that says everytime I’ll submit it:

TypeError: s.indexOf is not a function

import React, { useState } from "react";

const checkboxes = [
  { id: 1, text: "Checkbox 1" },
  { id: 2, text: "Checkbox 2" },
  { id: 3, text: "Checkbox 3" }
];

const SearchResults = () => {
  const [selectedCheckbox, setSelectedCheckbox] = useState([]);

  const handleChange = (id) => {
    const findIdx = selectedCheckbox.indexOf(id);

    if (findIdx > -1) {
      selectedCheckbox.splice(findIdx, 1);
    } else {
      selectedCheckbox.push(id);
    }
    setSelectedCheckbox(selectedCheckbox);
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(JSON.stringify(selectedCheckbox));
try {
      const userRef = db.collection("users").doc(uid);
      const ref = userRef.set({
        selectedCheckbox
      });
     console.log("done")
    } catch (err) {
      console.log(err);
    }
  };

  return (
    <div>
      <div className="App">
        <form onSubmit={handleSubmit}>
          {checkboxes.map((checkbox) => (
            <label key={checkbox.id}>
              {checkbox.text}
              <input
                type="checkbox"
                onChange={() => handleChange(checkbox.text)}
                selected={selectedCheckbox.includes(checkbox.id)}
              />
            </label>
          ))}
          <button type="submit">Submit</button>
        </form>
      </div>
      <p>Selected checkboxes: {JSON.stringify(selectedCheckbox)}</p>
    </div>
  );
};

This is the codesandbox, though there’s not Firestore data here: https://codesandbox.io/s/handle-multiple-checkboxes-in-react-forked-xehxf?file=/src/App.js:0-2520

Any help would be appreciated. Thank you.

Answer

I suspect the error rises when your tracking array of selectedCheckboxes goes undefined even though this is not quite the case in the linked code sandbox.

In React as a general rule, you should never mutate the state even using React hooks which is you case in the handleChange method.

You should update you event handler method as follows (always making a copy of the state array to construct a the new one):

const handleChange = (id) => {
    const findIdx = selectedCheckbox.indexOf(id);

    let selected;
    if (findIdx > -1) {
      selected = selectedCheckbox.filter((checkboxId) => checkboxId !== id);
    } else {
      selected = [...selectedCheckbox, id];
    }
    setSelectedCheckbox(selected);
};

You click event handler takes the checkbox id as an argument and you should update you click handler accordingly:

<label key={checkbox.id}>
    {checkbox.text}
    <input
        type="checkbox"
        onChange={() => handleChange(checkbox.id)}
        selected={selectedCheckbox.includes(checkbox.id)}
     />
</label>