Reputation: 450
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
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
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