在ReactJS中正确修改状态数组

fad*_*bee 365 javascript reactjs

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

this.state.arrayvar.push(newelement);
this.setState({arrayvar:this.state.arrayvar});
Run Code Online (Sandbox Code Playgroud)

我担心原地修改阵列push可能会造成麻烦 - 这样安全吗?

制作阵列副本的替代方案,setState这看起来很浪费.

Dav*_*ing 690

阵营的文档说:

把this.state看作是不可变的.

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

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

this.setState(prevState => ({
  arrayvar: [...prevState.arrayvar, newelement]
}))
Run Code Online (Sandbox Code Playgroud)

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

早期React版本的替代语法

您可以使用它concat来获得干净的语法,因为它返回一个新数组:

this.setState({ 
  arrayvar: this.state.arrayvar.concat([newelement])
})
Run Code Online (Sandbox Code Playgroud)

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

this.setState({
  arrayvar: [...this.state.arrayvar, newelement]
})
Run Code Online (Sandbox Code Playgroud)

  • 你能举例说明何时出现竞争条件? (8认同)
  • @Qiming`push`返回新的数组长度,这样就无法工作了.此外,`setState`是异步的,React可以将多个状态更改排队到单个渲染过程中. (3认同)
  • @mindeavor假设您有一个在this.state中查找参数的animationFrame,以及另一个在状态更改时更改其他参数的方法.可能存在一些状态已更改但未在侦听更改的方法中反映的帧,因为setState是异步的. (2认同)
  • 现在将状态数组视为不可变的简单方法是:`let list = Array.from(this.state.list); list.push( '呜'); this.setState({list});`修改你的风格偏好当然. (2认同)

Sta*_*ess 127

如果您正在使用,最简单ES6.

initialArray = [1, 2, 3];

newArray = [ ...initialArray, 4 ]; // --> [1,2,3,4]
Run Code Online (Sandbox Code Playgroud)

新阵列将是 [1,2,3,4]

React中更新你的状态

this.setState({
         arrayvar:[...this.state.arrayvar, newelement]
       });
Run Code Online (Sandbox Code Playgroud)

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

  • 这个问题的关键是改变React状态,而不是修改数组.你自己看了我的观点并编辑了你的答案.这使您的答案相关.做得好. (4认同)
  • 您的问题与OP问题无关 (2认同)
  • @Sisir 和任何想知道[如何更新状态中数组内的对象](/sf/ask/1968489071/)的人。 (2认同)

Rid*_*idd 55

最简单的方法ES6:

this.setState(prevState => ({
    array: [...prevState.array, newElement]
}))
Run Code Online (Sandbox Code Playgroud)


mos*_*ony 44

目前很多人面临更新 useState 钩子状态的问题。我使用这种方法安全地更新它并想在这里分享。

这就是我的状态

const [state, setState] = useState([])
Run Code Online (Sandbox Code Playgroud)

假设我有一个对象名称obj1,并且希望将其附加到我的状态中。我建议这样做

setState(prevState => [...prevState, obj1])
Run Code Online (Sandbox Code Playgroud)

这将安全地将对象插入到末尾并保持状态一致性

  • 当状态的新值取决于前一个值时,这是更新状态的正确方法。文档:*如果下一个状态取决于当前状态,我们建议使用更新函数形式:* `setState((state) => ...`,请参阅 https://en.reactjs.org/docs/react- component.html#setstate——状态更新不会立即发生,因此当使用原始状态变量时,某些更新可能会被新的更新覆盖。 (3认同)

Nea*_*leU 23

React可以批量更新,因此正确的方法是为setState提供执行更新的函数.

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

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

或者用于concat():

this.setState( state => ({
    array: state.array.concat([4])
}));
Run Code Online (Sandbox Code Playgroud)

以下显示了https://jsbin.com/mofekakuqi/7/edit?js,output是一个例子,如果你弄错了会发生什么.

setTimeout()调用正确添加了三个项目,因为React不会在setTimeout回调中批量更新(请参阅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'));
Run Code Online (Sandbox Code Playgroud)


Cla*_*kie 17

正如@nilgun在评论中提到的,你可以使用反应不变性助手.我发现这是非常有用的.

来自文档:

简单的推动

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

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

  • React immutability helper在文档中被描述为已弃用.现在应该使用https://github.com/kolodny/immutability-helper. (6认同)

Pav*_*van 13

如果你在 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);
Run Code Online (Sandbox Code Playgroud)


use*_*748 5

如果您正在使用功能组件,请按如下方式使用。

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
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

374180 次

最近记录:

6 年,6 月 前