改变 React 状态的首选方法是什么?

IT技术 javascript reactjs
2021-04-15 10:56:05

假设我有一个普通对象列表,this.state.list然后我可以用它来渲染一个孩子的列表。那么将对象插入的正确方法是什么this.state.list

下面是我认为它会起作用的唯一方法,因为您不能this.state像文档中提到的那样直接改变

this._list.push(newObject):
this.setState({list: this._list});

这对我来说似乎很丑陋。有没有更好的办法?

4个回答

concat 返回一个新数组,所以你可以做

this.setState({list: this.state.list.concat([newObject])});

另一种选择是 React 的immutability helper

  var newState = React.addons.update(this.state, {
      list : {
        $push : [newObject]
      }
  });

  this.setState(newState);
concat需要一个数组,所以你会想要this.state.list.concat([newObject]).
2021-05-26 10:56:05
使用从 this.state 派生的值调用 this.setState 会使您遇到更新批处理问题。请参阅stackoverflow.com/a/41445812/1998186,其中链接到 jsfiddle,显示您将遇到的问题。
2021-05-26 10:56:05
尽管我很欣赏不变性助手背后的想法(无论如何我最终可能会使用它),但Array.concat肯定比添加另一个库要好。
2021-06-02 10:56:05
@Heap 好吧,如果您将非数组传递给concat它会将其包装在一个数组中,但最好自己添加数组以使其显式:如果您有[[1,2], [3,4]]并想添加[5,6]为下一个元素,则需要执行.concat([[5,6]])其他操作会结束[[1,2], [3,4], 5, 6]
2021-06-11 10:56:05
@BenAlpert 在 Chrome 中为我工作,您是说这是非标准行为吗?
2021-06-20 10:56:05

可以使用函数作为参数调用setState()

this.setState((state) => ({ list: state.list.concat(newObj) }))

或在 ES5 中:

this.setState(function(state) {
  return {
   list: state.list.concat(newObj)
  }
})
这段代码是如何工作的?push 方法将返回 a NUMBER,它将在list变量上设置
2021-05-23 10:56:05
@Nyalab 您不应该将函数体包装在括号中吗?就目前在您的示例中的情况而言,粗箭头后面的大括号将开始一个块,而不是一个对象。像这样的东西:this.setState((state) => ({ list: state.list.push(newObj) }))
2021-06-06 10:56:05
@Arian:React 将执行所需的 DOM 更改指令,以便仅渲染新添加的元素。当然,您是新添加的元素不会改变先前元素的呈现方式。
2021-06-13 10:56:05
这是一个绝妙的答案,感觉比仅仅为了执行推送而连接数组要干净得多,尽管我猜这就是意见。
2021-06-14 10:56:05
你也可以使用splat: this.setState((state) => ({ list: [...state.list, newObj] }))
2021-06-15 10:56:05

2016 年更新

使用 ES6,您可以使用:

this.setState({ list: [...this.state.list, ...newObject] });
这不适用于批量更新。请参阅我在stackoverflow.com/a/41445812/1998186 上的示例
2021-05-22 10:56:05
...[newObject]和 just 一样newObject
2021-06-15 10:56:05

从react文档(https://facebook.github.io/react/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous):

因为 this.props 和 this.state 可能会异步更新,所以你不应该依赖它们的值来计算下一个状态。

所以你应该这样做:

this.setState((prevState) => ({
  contacts: prevState.contacts.concat([contact])
}));