在反应中更新嵌套状态

Posted

技术标签:

【中文标题】在反应中更新嵌套状态【英文标题】:Update Nested state in react 【发布时间】:2018-09-29 01:10:47 【问题描述】:

大家好,我正在尝试更新嵌套对象的状态,我目前正在这样做:

handleChange(target: id, value, type) 
    this.setState(
        state => (
            dwelling: (Object.assign(state.dwelling, [id]: [type]: value))
        )
    );

它来自一个表单组:

<FormGroup controlId="spaces">
    <ControlLabel>Dormitorios</ControlLabel>
    <FormControl
        componentClass="select"
        value=dwelling.spaces.dorms
        placeholder="Seleccione"
        onChange=e => this.handleChange(e, 'dorms')
    >

问题是,当我更新子对象 dwelling.spaces.dorms 的状态时,已创建但当我尝试放置另一个属性时,它会替换旧属性而不是添加:

Dwelling之前:


   address: "",
   currency: "",
   price: 0,
   publicationType: "",
   spaces: 
     closets: "",
     dorms: "",
     pools: ""
   ,
   subtype: "",
   type: ""

dwelling.spaces.dorms 的 onChange 之后


   address: "",
   currency: "",
   price: 0,
   publicationType: "",
   spaces: 
     dorms: "3",
   ,
   subtype: "",
   type: ""

dwelling.spaces.closets 的 onChange 之后


   address: "",
   currency: "",
   price: 0,
   publicationType: "",
   spaces: 
     closets: "3",
   ,
   subtype: "",
   type: ""

【问题讨论】:

【参考方案1】:

此示例使用 ES6 扩展运算符来保留您的旧属性,这相当于 Object.assign。

所以发生的事情是你没有保持你的嵌套价值。

this.setState(
  dwelling: 
    ...this.state.dwelling,
    [id]:  
      ...this.state.dwelling[id],
      [type]: value
      
  
);

在您的示例中,您用新对象覆盖了您的值。请注意下面的粗体字。

住宅:(Object.assign(state.dwelling, [id]: [type]: value))

在粗体文本中,它专门将一个新对象设置为 state.dwelling,而不保留旧值。所以我们所做的是使用 ES6 扩展运算符来帮助将旧值与新值合并

 
  ...this.state.dwelling[id],
  [type]: value
 

【讨论】:

我工作完美,我添加了state =&gt; 以保持其正常运行。最后一个是怎么回事? 发生的事情是您还需要在嵌套值Object.assign(state.dwelling, [id]: Object.assign(state.dwelling[id], [type]: value) ) 中使用 Object.assign 你用一个新值覆盖你的 [id] 并且你的新值从来没有得到旧的道具,这就是为什么你需要在嵌套值中使用 spread 或 Object.assign 你能解释一下你的代码做了什么来明确你的解决方案吗 感谢@KennethTruong 的精确,如果我理解得很好,在您的第一个示例的第一个序列中,在 setState 中,dwelling: ...this.state.dwelling, [id] 相当于this.state.dwelling.id【参考方案2】:

我将表单状态保存在一个复杂的对象中,为了简化我的代码,我在 TextField、Select 等引用的“handleChange”函数中使用了这个辅助函数。

export function updateObject(obj, keys, value) 
  let key = keys.shift();
  if (keys.length > 0) 
    let tmp = updateObject(obj[key], keys, value);
    return ...obj, [key]: tmp;
   else 
    return ...obj, [key]: value;
  

React-redux/Material-UI 示例

let [formState, changeFormState] = useState();

function handleChange(event) 
  changeFormState(updateObject(formState, event.target.name.split('.'), 
event.target.value));


<TextField className=classes.textfield name='foo.bar' value= 
formstate.foo.bar || '' onChange=handleChange />

【讨论】:

以上是关于在反应中更新嵌套状态的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法将状态信息从反应钩子传递到反应中的嵌套函数?

反应钩子:useState/context;无法读取未定义的属性“头像”/如何更新嵌套对象

使用 componentDidUpdate 在反应中更新状态

我们如何在反应中部分更新状态?

如何在反应中修复状态更新?

更新反应状态而不覆盖先前的状态