Correct way to push into state array

JavascriptReactjsImmutability

Javascript Problem Overview


I seem to be having issues pushing data into a state array. I am trying to achieve it this way:

this.setState({ myArray: this.state.myArray.push('new value') })

But I believe this is incorrect way and causes issues with mutability?

Javascript Solutions


Solution 1 - Javascript

Using es6 it can be done like this:

this.setState({ myArray: [...this.state.myArray, 'new value'] }) //simple value
this.setState({ myArray: [...this.state.myArray, ...[1,2,3] ] }) //another array

Spread syntax

Solution 2 - Javascript

Array push returns length

this.state.myArray.push('new value') returns the length of the extended array, instead of the array itself.Array.prototype.push().

I guess you expect the returned value to be the array.

Immutability

It seems it's rather the behaviour of React: > NEVER mutate this.state directly, as calling setState() afterwards may > replace the mutation you made. Treat this.state as if it were > immutable.React.Component.

I guess, you would do it like this (not familiar with React):

var joined = this.state.myArray.concat('new value');
this.setState({ myArray: joined })

Solution 3 - Javascript

> Never recommended to mutate the state directly.

The recommended approach in later React versions is to use an updater function when modifying states to prevent race conditions:

Push string to end of the array

this.setState(prevState => ({
  myArray: [...prevState.myArray, "new value"]
}))

Push string to beginning of the array

this.setState(prevState => ({
  myArray: ["new value", ...prevState.myArray]
}))

Push object to end of the array

this.setState(prevState => ({
  myArray: [...prevState.myArray, {"name": "object"}]
}))

Push object to beginning of the array

this.setState(prevState => ({
  myArray: [ {"name": "object"}, ...prevState.myArray]
}))

Solution 4 - Javascript

Functional Components & React Hooks

const [array,setArray] = useState([]);

Push value at the end:

setArray(oldArray => [...oldArray,newValue] );

Push value at the start:

setArray(oldArray => [newValue,...oldArray] );

Solution 5 - Javascript

You should not be operating the state at all. At least, not directly. If you want to update your array, you'll want to do something like this.

var newStateArray = this.state.myArray.slice();
newStateArray.push('new value');
this.setState(myArray: newStateArray);

Working on the state object directly is not desirable. You can also take a look at React's immutability helpers.

https://facebook.github.io/react/docs/update.html

Solution 6 - Javascript

Here you can not push the object to a state array like this. You can push like your way in normal array. Here you have to set the state,

this.setState({ 
     myArray: [...this.state.myArray, 'new value'] 
})

Solution 7 - Javascript

You can use .concat method to create copy of your array with new data:

this.setState({ myArray: this.state.myArray.concat('new value') })

But beware of special behaviour of .concat method when passing arrays - [1, 2].concat(['foo', 3], 'bar') will result in [1, 2, 'foo', 3, 'bar'].

Solution 8 - Javascript

Using react hooks, you can do following way

const [countryList, setCountries] = useState([]);


setCountries((countryList) => [        ...countryList,        "India",      ]);

Solution 9 - Javascript

This Code work for me :

fetch('http://localhost:8080')
  .then(response => response.json())
  .then(json => {
  this.setState({mystate: this.state.mystate.push.apply(this.state.mystate, json)})
})

Solution 10 - Javascript

React-Native

if u also want ur UI (ie. ur flatList) to be up to date, use PrevState: in the example below if user clicks on the button , it is going to add a new object to the list( both in the model and UI)

data: ['shopping','reading'] // declared in constructor
onPress={() => {this.setState((prevState, props) => {
return {data: [new obj].concat(prevState.data) };
})}}. 

Solution 11 - Javascript

In the following way we can check and update the objects

this.setState(prevState => ({
	Chart: this.state.Chart.length !== 0 ? [...prevState.Chart,data[data.length - 1]] : data
}));

Solution 12 - Javascript

you are breaking React principles, you should clone the old state then merge it with the new data, you shouldn't manipulate your state directly, your code should go like this

fetch('http://localhost:8080').then(response => response.json()).then(json ={this.setState({mystate[...this.state.mystate, json]}) })

Solution 13 - Javascript

  setState([...prevState, {
    label: newState.name,
    value: newState.id
  }]);

Was working with the dropdowns and wanted to implement this scenario there, i found this simple solution for dropdown with multiple values.

Solution 14 - Javascript

I guess this is a little bit late for an answer but for those new to react

You can use this tiny package called immer

see this example: https://immerjs.github.io/immer/produce

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIljaView Question on Stackoverflow
Solution 1 - JavascriptAliaksandr SushkevichView Answer on Stackoverflow
Solution 2 - JavascriptMárton TamásView Answer on Stackoverflow
Solution 3 - JavascriptHemadri DasariView Answer on Stackoverflow
Solution 4 - JavascriptPanagissView Answer on Stackoverflow
Solution 5 - JavascriptChristophView Answer on Stackoverflow
Solution 6 - JavascriptSachin MuthumalaView Answer on Stackoverflow
Solution 7 - JavascriptGindenView Answer on Stackoverflow
Solution 8 - JavascriptRajesh NasitView Answer on Stackoverflow
Solution 9 - JavascriptHamid HosseinpourView Answer on Stackoverflow
Solution 10 - JavascriptMahgol FaView Answer on Stackoverflow
Solution 11 - JavascriptKARTHIKEYAN.AView Answer on Stackoverflow
Solution 12 - JavascriptAhmed Muhammed ElsaidView Answer on Stackoverflow
Solution 13 - JavascriptMudassir KidwaiView Answer on Stackoverflow
Solution 14 - JavascriptNevin View Answer on Stackoverflow