在ReactJS中正确修改状态数组

本文翻译自:Correct modification of state arrays in ReactJS

I want to add an element to the end of a state array, is this the correct way to do it? 我想在state数组的末尾添加一个元素,这是正确的方法吗?

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? 我担心通过push就地修改数组可能会引起麻烦-是否安全?

The alternative of making a copy of the array, and setState ing that seems wasteful. 复制数组和setState替代方法似乎很浪费。


#1楼

参考:https://stackoom.com/question/1m9h9/在ReactJS中正确修改状态数组


#2楼

The React docs says: React文档说:

Treat this.state as if it were immutable. 将this.state视为不可变的。

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. 您的push将直接改变状态,即使您此后再次“重置”状态,也有可能导致易于出错的代码。 F.ex, it could lead to that some lifecycle methods like componentDidUpdate won't trigger. 例如,它可能导致某些生命周期方法(例如componentDidUpdate不会触发。

The recommended approach in later React versions is to use an updater function when modifying states to prevent race conditions: 在更高版本的React中,建议的方法是在修改状态以防止竞争情况时使用updater函数:

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 早期React版本的替代语法

You can use concat to get a clean syntax since it returns a new array: 您可以使用concat获得干净的语法,因为它返回一个新数组:

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

In ES6 you can use the Spread Operator : 在ES6中,您可以使用Spread运算符

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

#3楼

As @nilgun mentioned in the comment, you can use the react immutability helpers . 如评论中提到的@nilgun,您可以使用react 不可变性助手 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]. initialArray仍为[1、2、3]。


#4楼

Easiest, if you are using ES6 . 如果您使用的是ES6 ,则最简单。

initialArray = [1, 2, 3];

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

New array will be [1,2,3,4] 新数组将为[1,2,3,4]

to update your state in React React中更新您的状态

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

Learn more about array destructuring 了解有关数组解构的更多信息


#5楼

React may batch updates, and therefore the correct approach is to provide setState with a function that performs the update. React可能会批量更新,因此正确的方法是为setState提供执行更新的功能。

For the React update addon, the following will reliably work: 对于React更新插件,以下将可靠地工作:

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

or for concat(): 或对于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. 下面显示了https://jsbin.com/mofekakuqi/7/edit?js的输出,作为输出示例,说明如果弄错了怎么办。

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 ). setTimeout()调用正确添加了三个项目,因为React不会在setTimeout回调中批量更新(请参阅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. 越野车onClick仅会添加“第三”,而固定的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'));

#6楼

The simplest way with ES6 : ES6最简单的方法:

this.setState(prevState => ({
    array: [...prevState.array, newElement]
}))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值