我是否正确更新了React状态?

时间:2018-04-28 03:18:58

标签: javascript reactjs

在我的React状态下,我有状态:

this.state = {
  users: [{
    id: 1,
    name: "john",
    age: 27
  }, {
    id: 2,
    name: "ed",
    age: 18
  }, {
    id: 3,
    name: "mel",
    age: 20
  }]
}

我正确渲染name。当您单击名称时,它应该删除名称,该名称需要onClick,该{1}}接收函数并返回removeUser函数。

我的理解是你不想在React中改变状态,而是返回一个新的状态。所以,在我的removeUser函数中,我做了:

removeUser(index) {
  // Making a new copy of the array
  const users = [...this.state.people].splice(index, 1);
  this.setState({ users });
}

bind this.removeUser = this.removeUser.bind(this).我的方法Expected 1 to be 0

当我测试我的代码时,我正在按预期删除用户。但是,当我针对我朋友写的测试运行我的代码时,我得到了一个失败的测试说:class Group extends Component { constructor(props) { super(props); this.state = { users: [ {id: 1, name: "john", age: 27}, {id: 2, name: "ed", age: 18}, {id: 3, name: "mel", age: 20} ] } this.removeUser = this.removeUser.bind(this); } removeUser(index) { const users = [...this.state.users].splice(index, 1); this.setState({ users }); } render() { const list = this.state.users.map((user, i) => { return ( <div onClick={() => this.removeUser(i)} key={i}>{user.name}</div> ); }); return ( <div> {list} </div> ); } }

那条消息告诉我,我必须以某种方式改变状态,但我不确定如何。我是否正在返回一个新阵列并正确更新状态?有人可以向我解释在这种情况下我应该如何正确更新我的状态?

以下是完整代码:

def genBins(n):
    """
       generate all the binary strings with n-length
    """
    max_int = '0b' + '1' * n
    for i in range(0, int(max_int, 2)+1, 1):
        yield str(format(i, 'b').zfill(n))

if __name__ == '__main__':

    print(list(genBins(5)))

3 个答案:

答案 0 :(得分:2)

autoplot(m.ca.ppc, data = df.ca, label.size = 3, label=TRUE, label.label="community", shape=FALSE, which=1:6, ncol=3)

看起来它应该是从集合中删除一个项目,我认为它在技术上是。问题是const users = [...this.state.users].splice(index, 1) 不包含您要保留的用户列表。

相反,users已就地修改了新数组,然后返回已删除的项目:

splice docs

  

返回值

     

包含已删除元素的数组。如果仅删除一个元素,则返回一个元素的数组。如果没有删除任何元素,则返回一个空数组。

相反,如果您想使用splice,请创建一个新数组:

splice

然后拼接新数组:

const users = [...this.state.users]

如果您需要sort数组,则会遇到类似的问题。

通常不赞成就地修改数据的问题,赞成不可变引用。这是因为React使用大量对象的直接比较作为启发式方法来加快速度。如果您的函数修改了现有的对象实例,React将假定对象没有更改。

复制到新对象和然后对数据进行操作的行为需要进行一些权衡。对于删除单个项目,它可以忽略不计。要删除许多项目,您可以通过其他方法提供更好的服务,例如多个切片调用:

users.splice(index, 1)

然而,这也很冗长。

另一种方法是使用拼接的不可变变体:

const users = [
  ...this.state.users.slice(0, index)
  ...this.state.users.slice(index + 1)
]

答案 1 :(得分:2)

您也可以更改onClick并将user.id而不是索引传递给它。这将允许您过滤结果而不需要拼接数组。

onClick={() => this.removeUser(user.id)}

removeUser(id) {
  const users = this.state.users.filter((user) => user.id !== id);
  this.setState({ users });
}

答案 2 :(得分:0)

您应该使用slice()而不是splice(),因为splice()会改变原始数组,但slice()会返回一个新数组。 Slice()是一个纯函数。纯净更好!!

removeUser(index) {
    const users = [
    ...this.state.users.slice(0, index),
    ...this.state.users.slice(index+1)
    ];
    this.setState({ users });
  }

Here is JS Fiddle