可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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 am 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.
回答1:
The 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. F.ex, 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]
})
回答2:
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
回答3:
The simplest way with ES6
:
this.setState(prevState => ({
array: [...prevState.array, newElement]
}))
回答4:
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) => {
state.array = state.array.concat([4]);
return state;
});
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\'));
回答5:
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].
回答6:
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)})
})