在反应中更新嵌套状态
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 =>
以保持其正常运行。最后一个是怎么回事?
发生的事情是您还需要在嵌套值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;无法读取未定义的属性“头像”/如何更新嵌套对象