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?
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
this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state." In the case of modifying an array, since the array already exists as a property of this.state and you need to reference its value to set a new value, you should use the form of setState() that accepts a function with the previous state as an argument. Example: this.setState(prevState => ({ myArray: [...this.state.myArray, 'new value'] })); See: reactjs.org/docs/…const [array,setArray] = useState([]);
Push value at the end:
setArray(oldArray => [...oldArray,newValue] );
Push value at the start:
setArray(oldArray => [newValue,...oldArray] );
setArray(oldArray => [newValue,...oldArray] );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.
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):
this.setState({ myArray: [...this.state.myArray, 'new value'] })
console.log(this.state.myArray) it's always one behind. Any idea why?setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. So I guess it's just not updated at that moment right after setting it. Could You please post a code example, where we can see which point You are setting and logging it, please?.concat('new value'); should be .concat(['new value']);concat() method. See: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… (Arrays and/or values to concatenate into a new array.)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]
}))
this.setState((prevState) => ({ myArray: [values, ...prevState.myArray], }));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.
.slice() to create a new array and preserve immutability. Thanks for the help.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'].
Using react hooks, you can do following way
const [countryList, setCountries] = useState([]);
setCountries((countryList) => [
...countryList,
"India",
]);
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)})
})
fetch(`api.openweathermap.org/data/2.5/forecast?q=${this.searchBox.value + KEY} `) .then( response => response.json() ) .then( data => { this.setState({ reports: this.state.reports.push.apply(this.state.reports, data.list)}); }); this.state = { reports=[] }...pls i'll like to know what i'm doing wrongif 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) };
})}}.
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]}) })
It is the best and simplest way in reactJS if you working in functional components!
setSelectedTaxDec((oldArray) => [...oldArray, dec]);
oldArray is the previousState in which I am pushing the new value dec, is the value I am pushing in this state array
you can avoid pushing the same item again by doing this
if (selectedTaxDec.includes(dec)) {
return;
} else {
setSelectedTaxDec((oldArray) => [...oldArray, dec]);
}
If your array is too large for conventional [...oldArray, newValue] to be feasible (as it is O(N) complexity contrary to the O(1) complexity of .push() operation), you can wrap the array in an object to make sure to notify react of the update every time you mutate the array:
this.state = {
myArrayUpdateWrapper: {
myArray: [],
},
};
...
function pushToStateArray(newValue) {
const { myArray } = this.state.myArrayUpdateWrapper;
myArray.push(newValue);
this.setState({ myArrayUpdateWrapper: { myArray } });
}
I believe this approach is both compliant with React principles and is efficient too. Very surprised that nobody mentioned it so far, even in the downvoted answers.
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
Array.pushreturns the newlengthof the array instead of returning new array which causes issue