3

I'm trying to implement some functionality that will allow for the name of a checkbox to be pushed to an array in the components state and also to have that name removed when the checkbox is unchecked, I can push to the array just fine, it's removing items from it that I'm having trouble with.

I've tried using splice but the issue I'm having is it seems that the array is lagging one action behind, thus not allowing me to splice out the correct item.

handleCheckboxChange = event => {
  if (event.target.checked) {
    this.setState({
      check: [...this.state.check, event.target.name]
    });
} else if (!event.target.checked) {
    let index = this.state.check.indexOf(event.target.name);
    this.setState({
      check: this.state.check.splice(index, 1)
    });
  }
};

Expected result is that items will be added and removed from the array as the user checks or unchecks the corresponding checkbox.

1
  • Bear in mind, setState() is asynchronous. It may well happen as you expect, just not on the timeframe you expect. Commented Jan 23, 2019 at 22:50

2 Answers 2

3

According to the documentation of splice, it returns the removed items.

An array containing the deleted elements. If only one element is removed, an array of one element is returned. If no elements are removed, an empty array is returned.

So when you do this:

   this.setState({
      check: this.state.check.splice(index, 1)
    });

you are basically modifying directly this.state.check by using splice on it, and then setting it with this.setState({ check: [removed items] }).

you should don't modify state variables directly, and do something like this:

this.setState({
     check: this.state.check.filter((item, i) => {
          return index !== i;
     })
})

filter creates a new array, and do not modify the current array. You can also use slice which uses a shallow copy of the array, but I think this is more readable.

Sign up to request clarification or add additional context in comments.

Comments

1

An easy solution is .filter. MDN reference.

Also you should note that .splice is mutating the array, which means you're mutating the state object with .splice and then changing state with setState(), which means your altering it twice. I believe you want to avoid mutations and only change it with setState().

Try this solution, (some opinions about formatting were added in):

handleCheckboxChange = event => {
  const {checked, name} = event.target
  if (checked) {
    this.setState({
      check: [...this.state.check, name]
    });
} else {
    this.setState({
      check: this.state.check.filter(item => item !== name)
    });
  }
};

Edit: spaniard posted the same solution at the same time as me, but I'll leave this here as the implementations differ slightly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.