Removing element from array in component state
I am trying to find the best way to remove an element from an array in the state of a component. Since I should not modify the this.state
variable directly, is there a better way (more concise) to remove an element from an array than what I have here?:
onRemovePerson: function(index) {
this.setState(prevState => { // pass callback in setState to avoid race condition
let newData = prevState.data.slice() //copy array from prevState
newData.splice(index, 1) // remove element
return {data: newData} // update state
})
},
Thank you.
updated
This has been updated to use the callback in setState. This should be done when referencing the current state while updating it.
Solution 1:
The cleanest way to do this that I've seen is with filter
:
removeItem(index) {
this.setState({
data: this.state.data.filter((_, i) => i !== index)
});
}
Solution 2:
You could use the update()
immutability helper from react-addons-update
, which effectively does the same thing under the hood, but what you're doing is fine.
this.setState(prevState => ({
data: update(prevState.data, {$splice: [[index, 1]]})
}))
Solution 3:
I believe referencing this.state
inside of setState()
is discouraged (State Updates May Be Asynchronous).
The docs recommend using setState()
with a callback function so that prevState is passed in at runtime when the update occurs. So this is how it would look:
Using Array.prototype.filter without ES6
removeItem : function(index) {
this.setState(function(prevState){
return { data : prevState.data.filter(function(val, i) {
return i !== index;
})};
});
}
Using Array.prototype.filter with ES6 Arrow Functions
removeItem(index) {
this.setState((prevState) => ({
data: prevState.data.filter((_, i) => i !== index)
}));
}
Using immutability-helper
import update from 'immutability-helper'
...
removeItem(index) {
this.setState((prevState) => ({
data: update(prevState.data, {$splice: [[index, 1]]})
}))
}
Using Spread
function removeItem(index) {
this.setState((prevState) => ({
data: [...prevState.data.slice(0,index), ...prevState.data.slice(index+1)]
}))
}
Note that in each instance, regardless of the technique used, this.setState()
is passed a callback, not an object reference to the old this.state
;
Solution 4:
Here is a way to remove the element from the array in the state using ES6 spread syntax.
onRemovePerson: (index) => {
const data = this.state.data;
this.setState({
data: [...data.slice(0,index), ...data.slice(index+1)]
});
}