我不确定自己在做正确的事,我在setState之外对变量进行了突变,对吗?还是有更优雅的方法呢?

state = {
    persons: [{
      name: 'jay',
      age: 10
    }]
  }
  addRow = () => {
    const temp = this.state
    temp.persons.push({
      name: '',
      age: ''
    })
    this.setState({
      ...temp
    })
  }


应用演示https://codesandbox.io/s/ppqw4wjqzq

最佳答案

在javascript中,对象分配是通过Referece进行的,因此,即使您在setState之外对变量进行了更改,只要不克隆对象,它仍将引用相同的state引用。但是,如果克隆它,将创建一个新实例,并且原始实例将不受影响。

addRow = () => {
    const persons = [...this.state.persons] // Clone it one level deep using spread
    persons.push({
      name: '',
      age: ''
    })
    this.setState({
      persons
    })
  }


只需使用spread syntaxfunctional setState即可完成上述操作

addRow = () => {
    this.setState(prevState => ({
      persons: [...prevState.persons, { name: '', age: ''}]
    }))
  }


尽管在您的示例中这两个操作之间似乎没有什么区别,但是您提供的初始实现中存在重大缺陷。为了查看克隆和推送之间的区别以及仅分配引用和推送之间的区别,您可以看到codesandbox demo

基本上,当您创建一个新组件时,如果将状态人员作为道具传递给该组件,并在其原始引用处进行变异,则在componentWillReceiveProps方法中,您会看到currentPropsnextProps都相同,并且因此,如果您在子组件中进行了任何检查,如果这些人的道具发生了更改,该采取的措施就会失败。因此,极其重要的是不要根据自己的参考来改变值

如果没有push和spread语法,您仍然可以通过使用concat来避免突变问题,该concat可以创建原始数组的新副本

addRow = () => {
    this.setState(prevState => ({
      persons: prevState.persons.concat([{ name: '', age: ''}])
    }))
  }

关于javascript - 在es6中添加行而不推送,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52828574/

10-16 13:51