I have an array in state, let's say this.state.arr. I want to add something to this state property, and then change some more properties.
Option 1
onChange(event){
this.state.arr.push('newvalue');
...
this.setState({some:'val',arr:this.state.arr})
}
Option 2
onChange(event){
var newArr = this.state.arr;
...
newArr.push('newvalue');
...
this.setState({some:'val',arr:newArr})
}
So.. I know this.state is supposed to be treated immutable. But is it ok to use it like in option 1 where I still set the state from it, or do I need to go with something like option 2, and thus always first making a copy in memory
If you are using ES6 syntax you can use the spread operator to add new items to an existing array as a one liner.
// Append an array
const newArr = [1,2,3,4]
this.setState(prevState => ({
arr: [...prevState.arr, ...newArr]
}));
// Append a single item
this.setState(prevState => ({
arr: [...prevState.arr, 'new item']
}));
the best away now.
this.setState({ myArr: [...this.state.myArr, new_value] })
Both of the options you provided are the same. Both of them will still point to the same object in memory and have the same array values. You should treat the state object as immutable as you said, however you need to re-create the array so its pointing to a new object, set the new item, then reset the state. Example:
onChange(event){
var newArray = this.state.arr.slice();
newArray.push("new value");
this.setState({arr:newArray})
}
For functional components with hooks
const [searches, setSearches] = useState([]);
// Using .concat(), no wrapper function (not recommended)
setSearches(searches.concat(query));
// Using .concat(), wrapper function (recommended)
setSearches(searches => searches.concat(query));
// Spread operator, no wrapper function (not recommended)
setSearches([...searches, query]);
// Spread operator, wrapper function (recommended)
setSearches(searches => [...searches, query]);
source: https://medium.com/javascript-in-plain-english/how-to-add-to-an-array-in-react-state-3d08ddb2e1dc
If you want to keep adding a new object to the array i've been using:
_methodName = (para1, para2) => {
this.setState({
arr: this.state.arr.concat({para1, para2})
})
}
handleValueChange = (value) => {
let myArr= [...this.state.myArr]
myArr.push(value)
this.setState({
myArr
})
This might do the work.
For now, this is the best way.
this.setState(previousState => ({
myArray: [...previousState.myArray, 'new value']
}));
This might not directly answer your question but for the sake of those that come with states like the below
state = {
currentstate:[
{
id: 1 ,
firstname: 'zinani',
sex: 'male'
}
]
}
Solution
const new_value = {
id: 2 ,
firstname: 'san',
sex: 'male'
}
Replace the current state with the new value
this.setState({ currentState: [...this.state.currentState, new_array] })
onChange() {_x000D_
const { arr } = this.state;_x000D_
let tempArr = [...arr];_x000D_
tempArr.push('newvalue');_x000D_
this.setState({_x000D_
arr: tempArr_x000D_
});_x000D_
}
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
_x000D_
Source: Stackoverflow.com