Javascript ReactJS中状态数组的正确修改

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26253351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:37:20  来源:igfitidea点击:

Correct modification of state arrays in ReactJS

javascriptreactjs

提问by fadedbee

I want to add an element to the end of a statearray, 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 pushmight cause trouble - is it safe?

我担心就地修改数组push可能会导致麻烦 - 安全吗?

The alternative of making a copy of the array, and setStateing that seems wasteful.

制作数组副本的替代方法,而setStateing 似乎很浪费。

回答by David Hellsing

The React docssays:

阵营的文档说:

Treat this.state as if it were immutable.

将 this.state 视为不可变的。

Your pushwill 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 componentDidUpdatewon't trigger.

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

The recommended approach in later React versions is to use an updaterfunction when modifying states to prevent race conditions:

在后面的 React 版本中推荐的方法是在修改状态时使用更新程序函数来防止竞争条件:

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 concatto 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 中,您可以使用扩展运算符

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

回答by StateLess

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

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

回答by Ridd

The simplest way with ES6:

最简单的方法ES6

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

回答by NealeU

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,outputas 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 只会添加“第三个”,但固定的会按预期添加 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'));

回答by Clarkie

As @nilgun mentioned in the comment, you can use the react immutability helpers. I've found this to be super useful.

正如评论中提到的@nilgun,您可以使用 react immutability helpers。我发现这非常有用。

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]。

回答by user3444748

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

回答by Jagger

For added new element into the array, push()should be the answer.

对于将新元素添加到数组中,push()应该是答案。

For remove element and update state of array, below code works for me. splice(index, 1)can not work.

对于删除元素和更新数组状态,下面的代码对我有用。splice(index, 1)不能工作。

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

回答by Rajnikant Lodhi

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})
            })

回答by MadKad

This worked for me to add an array within an array

这对我在数组中添加数组有用

this.setState(prevState => ({
    component: prevState.component.concat(new Array(['new', 'new']))
}));

回答by ANUBHAV RAWAT

//------------------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;
}));