如何在不修改未提供新值的属性时更新对象状态?Reducer疑问
如何在不覆盖未传入属性的前提下更新对象状态?
你当前的代码问题在于显式硬编码了所有要更新的属性——如果action.endpoint里没有某个属性(比如origin),你还是会把它赋值进去,这时候该属性会变成undefined,直接覆盖原对象里的对应值,这显然不是你想要的。
解决这个问题很简单,直接利用对象展开运算符的特性,只合并action.endpoint中实际存在的属性:
case UPDATE_ENDPOINT: return <IState>state.map(endpoint => endpoint.ocid === action.endpoint.ocid ? { ...endpoint, // 先展开原对象,保留所有原有属性 ...action.endpoint // 再展开payload里的对象,只覆盖存在的属性 } : endpoint );
这样修改后,不管action.endpoint里只传了name和hostname,还是传了更多属性,都只会更新那些有新值的字段,原对象中未被传入的属性会完整保留。
如果担心action.endpoint里包含不需要的属性(比如ocid本身,虽然这里是用来匹配的,但万一payload里不小心改了ocid呢?),可以先解构出需要更新的字段,这样更严谨:
case UPDATE_ENDPOINT: // 解构出ocid用于匹配,剩下的都是要更新的字段 const { ocid, ...updatedFields } = action.endpoint; return <IState>state.map(endpoint => endpoint.ocid === ocid ? { ...endpoint, ...updatedFields } : endpoint );
本质上,对象展开运算符会按顺序合并属性:后面的对象中存在的属性会覆盖前面的同名属性,而不存在的属性不会对前面的对象产生任何影响——完美契合你“只更新传入的属性,保留其他属性”的需求。
内容的提问来源于stack exchange,提问作者vanegeek
相关产品推荐
相关产品推荐

