是否有可能更新对象的属性与setState?

喜欢的东西:

this.state = {
   jasper: { name: 'jasper', age: 28 },
}

我试过:

this.setState({jasper.name: 'someOtherName'});

这:

this.setState({jasper: {name: 'someothername'}})

第一个会导致语法错误,第二个则什么都不做。什么好主意吗?


当前回答

我知道这里有很多答案,但我很惊讶他们没有一个在setState之外创建一个新对象的副本,然后简单地setState({newObject})。干净、简洁、可靠。在这种情况下:

Const jasper ={…this.state。贾斯珀,名字:“另一个名字”} this.setState(() => ({jasper}))

或者动态属性(对表单非常有用)

Const jasper ={…this.state。jasper, [VarRepresentingPropertyName]: 'new value'} this.setState(() => ({jasper}))

其他回答

我用了这个方法。

如果你有一个这样的嵌套状态:

this.state = {
  formInputs:{
    friendName:{
      value:'',
      isValid:false,
      errorMsg:''
    },
    friendEmail:{
      value:'',
      isValid:false,
      errorMsg:''
    }
  }
}

你可以声明handleChange函数来复制当前状态并重新赋值

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let statusCopy = Object.assign({}, this.state);
    statusCopy.formInputs[inputName].value = inputValue;

    this.setState(statusCopy);
  }

这里是带有事件侦听器的HTML。确保使用与状态对象相同的名称(在本例中为'friendName')

<input type="text" onChange={this.handleChange} " name="friendName" />

第一种情况确实是语法错误。

因为我看不到组件的其余部分,所以很难理解为什么要在这里的状态中嵌套对象。在组件状态下嵌套对象不是一个好主意。尝试将初始状态设置为:

this.state = {
  name: 'jasper',
  age: 28
}

这样,如果你想要更新名称,你可以调用:

this.setState({
  name: 'Sean'
});

这能达到你的目标吗?

对于更大、更复杂的数据存储,我会使用Redux之类的东西。但这要高级得多。

关于组件状态的一般规则是只使用它来管理组件的UI状态(例如,活动,计时器等)。

看看这些参考资料:

https://facebook.github.io/react/docs/react-component.html#state https://facebook.github.io/react/docs/state-and-lifecycle.html

有多种方法可以做到这一点,因为状态更新是一个异步操作,所以要更新状态对象,我们需要使用setState的updater函数。

1-最简单的一个:

首先创建一个jasper的副本,然后做修改:

this.setState(prevState => {
  let jasper = Object.assign({}, prevState.jasper);  // creating copy of state variable jasper
  jasper.name = 'someothername';                     // update the name property, assign a new value                 
  return { jasper };                                 // return new object jasper object
})

而不是使用Object。我们也可以这样写:

let jasper = { ...prevState.jasper };

2-使用扩展语法:

this.setState(prevState => ({
    jasper: {                   // object that we want to update
        ...prevState.jasper,    // keep all other key-value pairs
        name: 'something'       // update the value of specific key
    }
}))

注意:对象。assign和Spread Operator只创建浅拷贝,所以如果你定义了嵌套对象或对象数组,你需要一种不同的方法。


更新嵌套状态对象:

假设你已经将state定义为:

this.state = {
  food: {
    sandwich: {
      capsicum: true,
      crackers: true,
      mayonnaise: true
    },
    pizza: {
      jalapeno: true,
      extraCheese: false
    }
  }
}

更新比萨饼对象的extraCheese:

this.setState(prevState => ({
  food: {
    ...prevState.food,           // copy all other key-value pairs of food object
    pizza: {                     // specific object of food object
      ...prevState.food.pizza,   // copy all pizza key-value pairs
      extraCheese: true          // update value of specific key
    }
  }
}))

更新对象数组:

让我们假设你有一个todo应用程序,你正在以这样的形式管理数据:

this.state = {
  todoItems: [
    {
      name: 'Learn React Basics',
      status: 'pending'
    }, {
      name: 'Check Codebase',
      status: 'pending'
    }
  ]
}

要更新任何todo对象的状态,在数组上运行一个map并检查每个对象的某个唯一值,如果condition=true,则返回具有更新值的新对象,否则返回相同的对象。

let key = 2;
this.setState(prevState => ({

  todoItems: prevState.todoItems.map(
    el => el.key === key? { ...el, status: 'done' }: el
  )

}))

建议:如果object没有唯一值,请使用数组索引。

这是另一个使用immer immutabe实用程序的解决方案,非常适合于深度嵌套的对象,并且您不应该关心突变

this.setState(
    produce(draft => {
       draft.jasper.name = 'someothername'
    })
)

不使用异步和等待使用此…

funCall(){    
     this.setState({...this.state.jasper, name: 'someothername'});
}

如果你使用异步和等待使用这个…

async funCall(){
      await this.setState({...this.state.jasper, name: 'someothername'});
}