正确修改ReactJS中的状态数组

我想添加一个元素到state数组的末尾,这是正确的方法吗?

 this.state.arrayvar.push(newelement); this.setState({arrayvar:this.state.arrayvar}); 

我担心的是,用push修改arrays可能会造成麻烦 – 是否安全?

制作数组副本的替代方法,以及setState ,这看起来很浪费。

React文档说:

把这个状态看作是不可变的。

您的push将直接改变状态,这可能会导致错误代码,即使您之后再次“重置”状态。 F.ex,可能会导致像componentDidUpdate这样的生命周期方法不会触发。

你会提到一个更好的select:

 var arrayvar = this.state.arrayvar.slice() arrayvar.push(newelement) this.setState({ arrayvar: arrayvar }) 

与使用非标准状态修改可能遇到的错误相比,内存“浪费”不是问题。

替代语法

你可以使用concat来获得更清晰的语法,因为它返回一个新的数组:

 this.setState({ arrayvar: this.state.arrayvar.concat([newelement]) }) 

在ES6中,您可以使用Spread Operator :

 this.setState({ arrayvar: [...this.state.arrayvar, newelement] }) 

在以后的React版本中,推荐的方法是使用更新函数而不是使用更多function语法的对象:

 this.setState(prevState => ({ arrayvar: [...prevState.arrayvar, newelement] })) 

最简单的,如果你正在使用ES6

 initialArray = [1, 2, 3]; newArray = [ ...initialArray, 4 ]; // --> [1,2,3,4] 

新数组将会是[1,2,3,4]

React中更新你的状态

 this.setState({arrayvar:[...this.state.arrayvar, newelement]}); 

了解有关数组解构的更多信息

正如评论中提到的@nilgun,你可以使用反应不变性帮手 。 我发现这是超级有用的。

从文档:

简单的推动

 var initialArray = [1, 2, 3]; var newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4] 

initialArray仍然是[1,2,3]。

React可能会批量更新,因此正确的方法是为setState提供执行更新的function。

对于React更新插件,以下将可靠地工作:

 this.setState( (state) => update(state, {array: {$push: [4]}}) ); 

或为concat():

 this.setState( (state) => { state.array = state.array.concat([4]); return state; }); 

下面显示了https://jsbin.com/mofekakuqi/7/edit?js输出的例子,如果你弄错了会发生什么。;

setTimeout()调用正确地添加了三个项目,因为React不会在setTimeoutcallback中批量更新(请参阅https://groups.google.com/d/msg/reactjs/G6pljvpTGX0/0ihYw2zK9dEJ )。

车上的onClick只会添加“第三”,但固定的,将按预期添加F,S和T.

 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')); 

ES6最简单的方法是:

 this.setState(prevState => ({ array: [...prevState.array, newElement] })) 

如果你愿意使用推,你可以做这样的事情:

 // wrong because push modify the array directly this.setState(prevState => ({ arrayvar: prevState.arrayvar.push(someElemet) && prevState.arrayvar, })); 

当然,更好的解决scheme是通过使用concat , slice或spread来避免突变。

看到这个video教程更多的解释。