You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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属性?


错误原因

你的代码存在两个关键逻辑错误,导致状态未正确更新:

  1. 数组长度判断错误:用itemObj.modifiers > 0和modifierObj.options > 0判断数组是否有内容,但数组是对象类型,直接与数字比较会返回false,应该使用length属性判断,比如itemObj.modifiers.length > 0。
  2. 不必要的条件过滤:仅对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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 04:30:56