'Checkbox selected for delete several reconds in React app

I am doing a to-do list app but I have trouble completing this. I am using a stupid method to remove the selected items. It works when I select the items sequentially but does not work to select non-sequentially.

For example- For sequentially: selected id:1,2,3,4, I filter both markers and isCheck are work.

For non-sequentially: selected id 1,3,4 It will show :

  • Uncaught TypeError: Cannot read properties of undefined (reading 'id')

I have two questions,

  1. Can I use for loop inside the filter? And how to use?
  2. How to solve the problem of undefined id?

Here is my code:

const [markers, setMarkers] = useState([]);

const [isCheck, setIsCheck] = useState([]);


const handleRemoveLocationAll = () => {
    

    setMarkers(
      markers.filter(
        (item) =>
          item.id.toString() !== isCheck[0].id &&
          item.id.toString() !== isCheck[1].id &&
          item.id.toString() !== isCheck[2].id &&
          item.id.toString() !== isCheck[3].id &&
          item.id.toString() !== isCheck[4].id &&
          item.id.toString() !== isCheck[5].id &&
          item.id.toString() !== isCheck[6].id &&
          item.id.toString() !== isCheck[7].id &&
          item.id.toString() !== isCheck[8].id
      )
    );

    
    // This is my selected item
    setIsCheck(
      isCheck.filter(
        (item) =>
          item.id.toString() !== isCheck[0].id &&
          item.id.toString() !== isCheck[1].id &&
          item.id.toString() !== isCheck[2].id &&
          item.id.toString() !== isCheck[3].id &&
          item.id.toString() !== isCheck[4].id &&
          item.id.toString() !== isCheck[5].id &&
          item.id.toString() !== isCheck[6].id &&
          item.id.toString() !== isCheck[7].id &&
          item.id.toString() !== isCheck[8].id
      )
    );
// Click Checkbox
  const handleClick = (e) => {
    const { id, checked } = e.target;
 
    setIsCheck([...isCheck, { id: id, checked: checked }]);

    if (!checked) {
      setIsCheck(isCheck.filter((item) => item.id !== id));
    }
  };
//And the component
<input
  type="checkbox"
  id={marker.id}
  name={marker.name}
  onChange={handleClick}
        />

Updated question- How I write something like that:

setMarkers(
      markers.filter((item) => {
        for (let i = 0; i < isCheck.length; i++) {
          item?.id.toString() !== isCheck[i]?.id;
        }
      })
    );

//to represent this
 setMarkers(
      markers.filter(
        (item) =>
          item.id.toString() !== isCheck[0]?.id &&
          item.id.toString() !== isCheck[1]?.id &&
          item.id.toString() !== isCheck[2]?.id &&
          item.id.toString() !== isCheck[3]?.id &&
          item.id.toString() !== isCheck[4]?.id &&
          item.id.toString() !== isCheck[5]?.id &&
          item.id.toString() !== isCheck[6]?.id &&
          item.id.toString() !== isCheck[7]?.id &&
          item.id.toString() !== isCheck[8]?.id
      )
    );


Solution 1:[1]

Q1 Can I use for loop inside the filter? And how to use?

Yes.

Your current filter code is a short version of running this

array.filter((element) => true) 
array.filter((element => { return true } )

both are equivalent

With the latter you could write more complex functions (see: When should I use a return statement in ES6 arrow functions)

So to use a loop you would just do

setMarkers(
    markers.filter(
      (item) => {

            /* loop here */ 

          return (
        item.id.toString() !== isCheck[0].id &&
        item.id.toString() !== isCheck[1].id &&
        item.id.toString() !== isCheck[2].id &&
        item.id.toString() !== isCheck[3].id &&
        item.id.toString() !== isCheck[4].id &&
        item.id.toString() !== isCheck[5].id &&
        item.id.toString() !== isCheck[6].id &&
        item.id.toString() !== isCheck[7].id &&
        item.id.toString() !== isCheck[8].id)
      }
    
    )
  );

Q2 How to solve the problem of undefined id?

This is because .id doesn't exist in one your objects. It seems you are trying to read id from an object that does not exist (thanks @compuercarguy for clarification)

Unsure if that is intended but you could solve this from erroring by using optional chaining

e.g. write this instead

item?.id.toString() !== isCheck[0]?.id

see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

Edit: to illustrate loop in your example

setMarkers(
    markers.filter(
      (item) => {
          for(let i = 0; i < isChecked.length; i++) {
              if(item.id.toString() ===  isCheck[i].id) {
                return false
              }
          }
          return true
      }

    )
  );

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1