AdamSulc
AdamSulc

Reputation: 450

Remove clicked value from state

I am using react-admin framework. I am trying to dynamically remove value from state (id), if the value is in the state present more than once. My use case is to create checkboxes, so if one checkbox is clicked twice it deselects.

So far I have this code:

private addIdsToObj = (id: any) => {
   const Ids = [...this.state.selectedIds, id];
   this.setState({ selectedIds: Ids });
   if (Object.values(this.state.selectedIds).includes(id) === true) {
      const index = this.state.selectedIds.indexOf(id);
      if (index > -1) {
           const newState = this.state.selectedIds.splice(index, 1);
           this.setState({ selectedIds: newState });
      }
   }
}

But it behaves weirdly. Right now it only removes every value from the state apart from the clicked one, that should be removed in the first place. I am really stuck with this.

Any ideas what I am doing wrong?

Thank you in advance.

Upvotes: 0

Views: 64

Answers (2)

irandoust
irandoust

Reputation: 552

First of all since the setState() is asynchronous, you should pass the following code inside a callback function, and since selectedIds is an array you don't need to use Object.values() on it (Because Object.values() returns an array of values of an object), this.state.selectedIds.includes(id) is enough. In addition, includes() return a true or false, so don't need to check its strict equality. Also, you should use slice() instead of splice, because splice() return an array of removed element. So your code should be something like this:

private addIdsToObj = (id: any) => {
    const Ids = [...this.state.selectedIds, id];
    this.setState({ selectedIds: Ids }, () => { // Put following code inside a callback function
        if (this.state.selectedIds.includes(id)) { // I removed `===` because includes() return true or false
            const index = this.state.selectedIds.indexOf(id);
            if (index > -1) {
                const newState = this.state.selectedIds.slice(index);
                this.setState({ selectedIds: newState });
            }
        }
    });
}

Upvotes: 0

minuteMed
minuteMed

Reputation: 887

I think the underlying problem is with this line:

const newState = this.state.selectedIds.splice(index, 1);

The splice method will return the removed element (here newState)

then in the next line, you're setting the state to that value (which the single removed state)

What you should do instead, since splice method will remove the element from the source array is to pass selectedIds to setState() method

this.setState({ selectedIds: this.state.selectedIds });

Upvotes: 1

Related Questions