admin管理员组文章数量:1125967
I want to add an element to the end of a state
array, is this the correct way to do it?
this.state.arrayvar.push(newelement);
this.setState({ arrayvar:this.state.arrayvar });
I'm concerned that modifying the array in-place with push
might cause trouble - is it safe?
The alternative of making a copy of the array, and setState
ing that seems wasteful.
I want to add an element to the end of a state
array, is this the correct way to do it?
this.state.arrayvar.push(newelement);
this.setState({ arrayvar:this.state.arrayvar });
I'm concerned that modifying the array in-place with push
might cause trouble - is it safe?
The alternative of making a copy of the array, and setState
ing that seems wasteful.
- 12 I think you can use react immutability helpers. see this: facebook.github.io/react/docs/update.html#simple-push – nilgun Commented Oct 8, 2014 at 10:02
- 1 setState in state array check my solution.<br/> <br> stackoverflow.com/a/59711447/9762736 – Rajnikant Lodhi Commented Jan 13, 2020 at 8:13
19 Answers
Reset to default 991The React docs says:
Treat this.state as if it were immutable.
Your push
will mutate the state directly and that could potentially lead to error prone code, even if you are "resetting" the state again afterwards. For example, it could lead to that some lifecycle methods like componentDidUpdate
won’t trigger.
The recommended approach in later React versions is to use an updater function when modifying states to prevent race conditions:
this.setState(prevState => ({
arrayvar: [...prevState.arrayvar, newelement]
}))
The memory "waste" is not an issue compared to the errors you might face using non-standard state modifications.
Alternative syntax for earlier React versions
You can use concat
to get a clean syntax since it returns a new array:
this.setState({
arrayvar: this.state.arrayvar.concat([newelement])
})
In ES6 you can use the Spread Operator:
this.setState({
arrayvar: [...this.state.arrayvar, newelement]
})
Easiest, if you are using ES6
.
initialArray = [1, 2, 3];
newArray = [...initialArray, 4]; // --> [1,2,3,4]
New array will be [1,2,3,4]
to update your state in React
this.setState({
arrayvar: [...this.state.arrayvar, newelement]
});
Learn more about array destructuring
The simplest way with ES6
:
this.setState(prevState => ({
array: [...prevState.array, newElement]
}))
Currently so many people facing problem to update the useState hook state. I use this approach to update it safely and wanted to share it here.
This is my state
const [state, setState] = useState([])
Suppose I have a object name obj1
and I want it to append in my state. I will suggest to do it like this
setState(prevState => ([...prevState, obj1]))
This will safely insert the object at the end and also keep the state consistency
React may batch updates, and therefore the correct approach is to provide setState
with a function that performs the update.
For the React update addon, the following will reliably work:
this.setState(state => update(state, {array: {$push: [4]}}));
or for concat():
this.setState(state => ({
array: state.array.concat([4])
}));
The following shows what https://jsbin.com/mofekakuqi/7/edit?js,output as an example of what happens if you get it wrong.
The setTimeout()
invocation correctly adds three items because React will not batch updates within a setTimeout
callback (see https://groups.google.com/d/msg/reactjs/G6pljvpTGX0/0ihYw2zK9dEJ).
The buggy onClick
will only add "Third", but the fixed one, will add F
, S
and T
as expected.
class List extends React.Component {
constructor(props) {
super(props);
this.state = {
array: []
}
setTimeout(this.addSome, 500);
}
addSome = () => {
this.setState(
update(this.state, {array: {$push: ["First"]}}));
this.setState(
update(this.state, {array: {$push: ["Second"]}}));
this.setState(
update(this.state, {array: {$push: ["Third"]}}));
};
addSomeFixed = () => {
this.setState( state =>
update(state, {array: {$push: ["F"]}}));
this.setState( state =>
update(state, {array: {$push: ["S"]}}));
this.setState( state =>
update(state, {array: {$push: ["T"]}}));
};
render() {
const list = this.state.array.map((item, i) => {
return <li key={i}>{item}</li>
});
console.log(this.state);
return (
<div className='list'>
<button onClick={this.addSome}>add three</button>
<button onClick={this.addSomeFixed}>add three (fixed)</button>
<ul>
{list}
</ul>
</div>
);
}
};
ReactDOM.render(<List />, document.getElementById('app'));
If you are using functional components in React
const [cars, setCars] = useState([{
name: 'Audi',
type: 'sedan'
}, {
name: 'BMW',
type: 'sedan'
}])
...
const newCar = {
name: 'Benz',
type: 'sedan'
}
const updatedCarsArray = [...cars, newCar];
setCars(updatedCarsArray);
As @nilgun mentioned in the comment, you can use the react immutability helpers. I've found this to be super useful.
From the docs:
Simple push
var initialArray = [1, 2, 3];
var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
initialArray is still [1, 2, 3].
If you are using functional component please use this as below.
const [chatHistory, setChatHistory] = useState([]); // define the state
const chatHistoryList = [...chatHistory, {'from':'me', 'message':e.target.value}]; // new array need to update
setChatHistory(chatHistoryList); // update the state
this.setState(preState => ({ arrayvar: [...prevState.arrayvar,newelement] }))
This will work to solve this problem.
For added new element into the array, push()
should be the answer.
For remove element and update state of array, below code works for me. splice(index, 1)
can not work.
const [arrayState, setArrayState] = React.useState<any[]>([]);
...
// index is the index for the element you want to remove
const newArrayState = arrayState.filter((value, theIndex) => {return index !== theIndex});
setArrayState(newArrayState);
What I do is update a value outside the state and do a forceupdate(), the less stuff managed by react the better since you have more control over what is updated. Also creating a new array for every update may be too expensive if the updates are fast
First method is for class components second is for functional components
constructor (props){
super();
this.state = {
quote : [],
}
this.setState({
quote : [...this.state.quote , newObj]
})
const [quote, setQuote] = useState([])
setQuote(prevState => [...prevState, newObj])
Here's a 2020, Reactjs Hook example that I thought could help others. I am using it to add new rows to a Reactjs table. Let me know if I could improve on something.
Adding a new element to a functional state component:
Define the state data:
const [data, setData] = useState([
{ id: 1, name: 'John', age: 16 },
{ id: 2, name: 'Jane', age: 22 },
{ id: 3, name: 'Josh', age: 21 },
]);
Have a button trigger a function to add a new element
<Button
// pass the current state data to the handleAdd function so we can append to it.
onClick={() => handleAdd(data)}>
Add a row
</Button>
function handleAdd(currentData) {
// return last data array element
let lastDataObject = currentTableData[currentTableData.length - 1]
// assign last elements ID to a variable.
let lastID = Object.values(lastDataObject)[0]
// build a new element with a new ID based off the last element in the array
let newDataElement = {
id: lastID + 1,
name: 'Jill',
age: 55,
}
// build a new state object
const newStateData = [...currentData, newDataElement]
// update the state
setData(newStateData);
// print newly updated state
for (const element of newStateData) {
console.log('New Data: ' + Object.values(element).join(', '))
}
}
I am trying to push value in an array state and set value like this and define state array and push value by map function.
this.state = {
createJob: [],
totalAmount: Number = 0,
}
your_API_JSON_Array.map((_) => {
this.setState({ totalAmount:this.state.totalAmount += _.your_API_JSON.price })
this.state.createJob.push({ id: _._id, price: _.your_API_JSON.price })
return this.setState({ createJob: this.state.createJob })
})
I was having a similar issue when I wanted to modify the array state while retaining the position of the element in the array.
This is a function to toggle between like and unlike:
const liker = (index) => {
setData((prevState) => {
prevState[index].like = ! prevState[index].like;
return [...prevState];
});
}
As we can say the function takes the index of the element in the array state, and we go ahead and modify the old state and rebuild the state tree.
This worked for me to add an array within an array
this.setState(prevState => ({
component: prevState.component.concat(new Array(['new', 'new']))
}));
//get the value you want to add
const valor1 = event.target.elements.valor1.value;
//add in object
const todo = {
valor1,
}
//now you just push the new value into the state
//prevlista is the value of the old array before updating, it takes the old array value makes a copy and adds a new value
setValor(prevLista =>{
return prevLista.concat(todo) })
//------------------code is return in typescript
const updateMyData1 = (rowIndex:any, columnId:any, value:any) => {
setItems(old => old.map((row, index) => {
if (index === rowIndex) {
return Object.assign(Object.assign({}, old[rowIndex]), { [columnId]: value });
}
return row;
}));
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)})
})
本文标签: javascriptCorrect modification of state arrays in ReactjsStack Overflow
版权声明:本文标题:javascript - Correct modification of state arrays in React.js - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736677276a1947246.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论