【问题标题】:NGRX - can't set the state tree as I would like it to beNGRX - 无法按照我的意愿设置状态树
【发布时间】:2018-09-09 21:48:11
【问题描述】:

所以我使用 ngrx 来管理我的应用程序中的状态。我尝试添加一个应该如下所示的新属性(选定的班次):

state: {
    shifts: {
        selectedShifts: [
            [employeeId]: [
                [shiftId]: shift
            ]
        ]
    }
}

目前,我的状态是这样的:

state: {
    selectedShifts: {
        [employeeId]: {
            [shiftId]: shift
        }
    }
}

如您所见,我的“选定班次”是一个属性,而不是一个数组 - 这使得添加/删除/查询状态变得困难。

如何将状态组合成我想要的样子?

这是我在减速器中尝试的:

return {
    ...state,
    selectedShifts: {
      ...state.selectedShifts,
      [action.payload.employeeId]: {
        ...state.selectedShifts[action.payload.employeeId],
        [action.payload.shiftId]: action.payload[shift.shiftId]
      }
    }
  };

现在,当我尝试以我想要的方式返回状态时,结果如下:

state: {
    selectedShifts: {
        [action.payload.employeeId]: 
            [0]: {[action.payload.shiftId]: { shift }}
    }
}

我在这里缺少什么?当我尝试替换应为 [] 的 {} 项时,出现此错误:“,”预期。

哦,是的,我希望数组的索引是特定班次的 id 而不是 [0]、[1]...

这可能吗? 将索引从数字更改为实际班次的 id 会不会是个坏主意?

【问题讨论】:

    标签: arrays typescript ngrx ngrx-store


    【解决方案1】:

    当您在数字索引点添加数据时,会出现数组长度类型的缺失。这可能会让您遇到使用长度连接、切片、indexOf 等数组方法和改变长度推送、拼接等数组方法的问题。

    var fruits = [];
    fruits.push('banana', 'apple', 'peach');
    
    console.log(fruits.length); // 3
    

    当属性是有效的数组索引并且该索引超出数组的当前边界时,在 JavaScript 数组上设置属性时,引擎将相应地更新数组的长度属性:

    fruits[5] = 'mango';
    console.log(fruits[5]); // 'mango'
    console.log(Object.keys(fruits));  // ['0', '1', '2', '5']
    console.log(fruits.length); // 6
    

    从对象中选择/更新状态没有问题,这与您可能习惯的有点不同。使用直接 hashmap { objectId: Object } 如果为对象 id 定义了更改,则可以最快地找到更新/删除所需的对象。

    我知道您的问题与 NGRX 有关,但阅读 Redux 不可变模式肯定会帮助您在这里添加/更新/删除状态中的对象。 https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns

    通常你不想让数组处于状态(至少是大数组)对象哈希图要好得多。

    要获取您选择的用户视图的数组,您可以执行类似的操作。请注意,这不是一个移位索引数组,只是 userId 属性下的移位数组。从原始状态形成跟随状态。

    state: {
        selectedShifts: {
            [employeeId]: {
                [shiftId]: shift
            }
        }
    }
    
    const getSelectedShiftsAsArray = this.store.select( getSelectedShifts() )
    .map(
        userShifts => {
            // get array of object ids
            const userIds = Object.keys( userShifts );
    
            const ret = {};
    
            for( const userId of userIds ) { 
                const collectedShifts = [];
                // convert Dictionary<Shift> into a Shift[]
                // get array of shift ids
                const shiftIds = Object.keys( userShifts[userId] );
                // map array of shift ids into shift object array
                collectedShifts = shiftIds.map( shiftId => userShifts[shiftId] );
                // return value for a userId
                ret[userId] = collectedShifts;
    
            }
    
            return ret;
    });
    

    代码完全未经测试,仅供参考,比伪代码高一级。不过,您可以轻松地将其转换为 NGRX 选择器。状态仅用于存储,如何对其建模以在组件中使用取决于选择器函数和组件本身。

    如果你真的需要,你可以添加。

    ret[userId].shiftIds = shiftIds;
    ret[userId].shifts = collectedShifts;
    

    但这真的取决于你打算如何使用这些。

    根据我的个人经验,我会将班次实体与 selectedShifts 分开,但您如何组织您的状态完全取决于您。

    state: {
        shifts: {
            // contains shift entities as object property map id: entity
            entities: Dictionary<Shift>,
            selectedShifts: [
                [employeeId]: number[] // contains ids for shifts
            ]
        }
    }
    

    现在更新/删除和添加班次只是将更新的数据设置到路径 shifts.entities[entityId]

    employeeId 的 selectedShifts 也是关于检查 id 是否已经存在,如果不存在则将其附加到数组中。 (如果这些数组非常庞大,我也会在这里使用对象哈希以快速访问。&lt;employeeId&gt;: {shiftId:shiftId})。

    同时检查: redux: state as array of objects vs object keyed by id

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 2014-02-10
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      相关资源
      最近更新 更多