使用 Redux Toolkit 的 createEntityAdapter 进行动态数据网格

Jak*_*one 0 javascript reactjs redux redux-toolkit

我有一个关于使用Redux ToolkitcreateEntityAdapter的问题。

我有一个应用程序,它使用AG 网格库的主/详细信息功能来显示包和包详细信息。应用程序首先加载包数据,然后在扩展每个包行时获取详细数据。

我想用createEntityAdapter规范化的方式管理数据,但我无法弄清楚如何处理详细网格的动态特性。现在,我有一个减速器切片,每次加载一组详细记录时都会创建一个新属性。属性键是id父包行的,因此在加载data包数据和详细数据后,我的切片最终看起来像这样:123

{
  PACKAGES: [{ id: 123, ...otherData }, { id: 124, ...otherData }],
  '123': [{ id: 456, ...otherDetailData }],
}
Run Code Online (Sandbox Code Playgroud)

当用户展开124包行时,会获取该包的详细数据,然后如下所示:

{
  PACKAGES: [{ id: 123, ...otherData }, { id: 124, ...otherData }],
  '123': [{ id: 456, ...otherDetailData }],
  '124': [{ id: 457, ...otherDetailData }],
}
Run Code Online (Sandbox Code Playgroud)

因此,虽然我可以将数据分解PACKAGES到其自己的实体适配器中,但我无法对详细网格执行相同的操作,因为我事先并不了解每个网格。

我想我和这个问题的人有类似的问题。

我考虑过将所有详细数据存储在单个实体适配器中,并由父级维护另一个索引id,但这似乎很难保持同步。

有任何想法吗?这种情况下的最佳实践是什么?

mar*_*son 5

我创建并维护了 Redux Toolkit,实际上我最近确实使用嵌套实体适配器做了一些类似的事情。

就我而言,我需要在添加或删除父项时维护这些辅助数据集。

interface ChildrenEntry {
  parentId: ParentId;
  children: EntityState<ChildType>
}

interface ChildrenData {
  parentId: ParentId;
  children: ChildType[];
}

interface NewChildAdded {
  parentId: ParentId;
  child: ChildType;
}

export const childEntriesAdapter = createEntityAdapter<ChildrenEntry>();
export const childrenAdapter = createEntityAdapter<ChildType>();

const initialState = childEntriesAdapter.getInitialState();

const createNewChildEntry = (parentId: ParentId) => ({
  parentId,
  children: childrenAdapter.getInitialState()
});

const childEntriesSlice = createSlice({
  name: "children",
  initialState,
  reducers: {
    childEntriesLoaded(state, action: PayloadAction<ChildrenData>) {
      const {parentId, children} = action.payload;
      const childEntry = state.entities[parentId];
      if (childEntry) {
        childrenAdapter.setAll(childEntry.children, children);
      }
    },
    // etc
  },
  extraReducers: builder => {
    builder
      .addCase(parentLoaded, (state, action) => {
        const childEntries = action.payload.map(parent => createNewChildEntry(parent.id));
        childEntriesAdapter.setAll(state, childEntries);
      })
      .addCase(parentDeleted, (state, action) => {
        childEntriesAdapter.removeOne(state, action);
      })
      .addCase(parentAdded, (state, action) => {
        const childEntry = createNewChildEntry(action.payload.id);
        childEntriesAdapter.addOne(state, childEntry);
      });
  }
})
Run Code Online (Sandbox Code Playgroud)

可能有更好的方法来处理这个问题,但它足以满足我的需求。