What is the best way to add a value to an array in state
MemoryStateReactjsMemory Problem Overview
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
Memory Solutions
Solution 1 - Memory
For now, this is the best way.
this.setState(previousState => ({
myArray: [...previousState.myArray, 'new value']
}));
Solution 2 - Memory
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})
}
Solution 3 - Memory
Another simple way using concat:
this.setState({
arr: this.state.arr.concat('new value')
})
Solution 4 - 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']
}));
Solution 5 - Memory
Short way with useState
hook:
const [value, setValue] = useState([])
setValue([...value, newvalue])
Solution 6 - Memory
the best away now.
this.setState({ myArr: [...this.state.myArr, new_value] })
Solution 7 - Memory
onChange() {
const { arr } = this.state;
let tempArr = [...arr];
tempArr.push('newvalue');
this.setState({
arr: tempArr
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Solution 8 - Memory
handleValueChange = (value) => {
let myArr= [...this.state.myArr]
myArr.push(value)
this.setState({
myArr
})
This might do the work.
Solution 9 - Memory
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
Solution 10 - Memory
React hook - useState (2022)
const [array, setArray] = useState([]);
const handleChange = (newValue) => {
setArray((array) => [...array, newValue]);
};
Solution 11 - Memory
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})
})
}
Solution 12 - Memory
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] })