React/React Native中重置嵌套对象数组的is_selected状态方法
React/React Native 嵌套状态重置问题
我在React/React Native中用useState定义了如下嵌套状态:
const [shopRecord, setShopRecord] = useState({ shopSetting: { shop_name: '', shop_address: '', shop_tel: '', shop_email: '', }, menuCourse: [ { name: 'Fish', items: [ { id: '1', name: 'Fish & Chips Deal', is_selected: 1, modifiers: [ { title: 'Select one option', options: [ { name: 'Medium Cod', stockno: '102', is_selected: 1, price: 0, }, { name: 'Medium Haddock', stockno: '103', is_selected: 0, price: 0, }, ], }, { title: 'Select one option', options: [ { name: 'Medium Chips', stockno: '106', is_selected: 1, price: 0, }, { name: 'Large Chips', stockno: '107', is_selected: 0, price: 60, }, ], }, { title: 'Select one option', options: [ { name: 'Salt', stockno: '108', is_selected: 1, price: 0, }, ], }, { title: 'Select one option', options: [ { name: 'Mushy Peas', stockno: '112', is_selected: 0, price: 0, }, { name: 'Curry Sauce', stockno: '114', is_selected: 1, price: 0, }, ], }, { title: 'Select an option', options: [ { name: 'Rubicon Guava', stockno: '119', is_selected: 0, price: 100, }, { name: 'Vimto', stockno: '121', is_selected: 1, price: 100, }, ], }, ], price: 1080, }, ], }, ], });
我通过FlatList组件基于这个状态渲染菜单列表,用户点击options选项时能正常将对应is_selected设为1。现在需要实现:用户点击“加入购物车”按钮后,把选中的items存入存储,然后将所有层级的is_selected属性重置为0,且不能直接修改原状态。
我尝试了以下代码,但控制台输出显示状态没有变化:
setShopRecord(prevState => { return { ...prevState, menuCourse: prevState.menuCourse.map(menuObj => menuObj.items.length > 0 ? { ...menuObj, items: menuObj.items.map(itemObj => itemObj.modifiers > 0 ? { ...itemObj, is_selected: 0, modifiers: itemObj.modifiers.map(modifierObj => modifierObj.options > 0 ? { ...modifierObj, options: modifierObj.options.map(optionObj => optionObj.is_selected == 1 ? {...optionObj, is_selected: 0} : optionObj, ), } : modifierObj, ), } : {...itemObj, is_selected: 0}, ), } : menuObj, ), }; });
请问我哪里出错了?怎么正确实现不修改原状态的前提下,更新多层嵌套对象中的所有is_selected属性?
错误原因
你的代码存在两个关键逻辑错误,导致状态未正确更新:
- 数组长度判断错误:用
itemObj.modifiers > 0和modifierObj.options > 0判断数组是否有内容,但数组是对象类型,直接与数字比较会返回false,应该使用length属性判断,比如itemObj.modifiers.length > 0。 - 不必要的条件过滤:仅对
is_selected == 1的选项执行重置操作,但需求是将所有is_selected设为0,这个判断会跳过原本值为0的选项,导致状态更新不完整。
正确实现代码
以下是修正后的代码,严格遵循不可变更新原则,逐层拷贝嵌套对象/数组,同时重置所有is_selected为0:
setShopRecord(prevState => { // 拷贝顶层状态对象 return { ...prevState, // 遍历menuCourse数组,生成新数组 menuCourse: prevState.menuCourse.map(menuObj => ({ ...menuObj, // 遍历items数组,生成新数组并重置item的is_selected items: menuObj.items.map(itemObj => ({ ...itemObj, is_selected: 0, // 遍历modifiers数组,生成新数组 modifiers: itemObj.modifiers.map(modifierObj => ({ ...modifierObj, // 遍历options数组,生成新数组并重置每个option的is_selected options: modifierObj.options.map(optionObj => ({ ...optionObj, is_selected: 0 })) })) })) })) }; });
代码说明
- 每一层嵌套的数组或对象都通过展开运算符(
...)创建新的拷贝,确保不会修改原状态。 - 直接将所有层级的
is_selected设为0,无需判断原有值,简化逻辑的同时保证更新完整。 - 移除了多余的长度判断:即使
items、modifiers或options为空数组,map方法会直接返回空数组,不影响整体逻辑。
内容的提问来源于stack exchange,提问作者Atif Gulzar
相关产品推荐
相关产品推荐

