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.
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)
});
}
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]]})
}))
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
;