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

React与Redux中规范化状态下ID引用映射的高效实现方案

Redux规范化状态结构的映射实现问题

我刚开始学习Redux,已经按照官方文档《Normalizing State Shape》章节的核心规范——任何对单个项的引用都应通过存储项的ID来实现——构建了状态结构,示例如下:

{
    "taskGroups": {
        "byId": {
            "taskGroup1": {
                "taskGroupId": "taskGroup1",
                "tasks": ["task1", "task2"]
                // etc etc
            },
            "taskGroup2": {
                "taskGroupId": "taskGroup2",
                "tasks": ["task2", "task3"]
                // etc etc
            }
            // etc etc
        },
        "allIds": ["taskGroup1", "taskGroup2", "taskGroup3"]
    },
    "tasks": {
        "byId": {
            "task1": {
                "taskId": "task1",
                "description": "......",
                "comments": ["comment1", "comment2"]
                // etc etc
            },
            "task2": {
                "taskId": "task2",
                "description": "......",
                "comments": ["comment3", "comment4", "comment5"]
                // etc etc
            }
            // etc etc
        },
        "allIds": ["task1", "task2", "task3", "task4"]
    },
    "comments": {
        "byId": {
            "comment1": {
                "id": "comment1",
                "comment": "....."
                // etc etc
            },
            "comment2": {
                "id": "comment2",
                "comment": "....."
                // etc etc
            }
            // etc etc
        },
        "allIds": ["comment1", "comment2", "comment3", "comment4", "comment5"]
    }
}

我理解这种结构的理论优势,但实践中遇到两个核心问题:

  • 不确定ID数组的映射逻辑应该放在哪里:是在父组件中完成映射后传递给子组件,还是把ID引用传到子组件里再处理?
  • 之前用useContext配合规范化状态时,我写了一个筛选函数来匹配taskGroup对应的任务:
export const filterObject = (objToFilter: any, valuesToFind: string[]) => {
    return Object.keys(objToFilter)
        .filter((key) => valuesToFind.includes(key))
        .reduce((obj, key) => {
            return {
                ...obj,
                [key]: objToFilter[key],
            };
        }, {});
};

然后在组件中这样使用(Tasks组件里也用相同逻辑映射评论):

{
    Object.values(taskGroupsById)
        .sort((a, b) => a.sortOrder - b.sortOrder)
        .map((taskGroup) => {
            return (
                <TaskGroup
                    key={taskGroup.taskGroupId}
                    taskGroupTitle={taskGroup.taskGroupTitle}
                    tasks={filterObject(
                        tasksById,
                        taskGroup.tasks
                    )}
                    handleDrawer={handleDrawer}
                    findTaskStatus={findTaskStatus}
                    findAssignedToTask={findAssignedToTask}
                />
            );
        });
}

这个方法能正常运行,但每个TaskGroup实例都会重复执行筛选逻辑,存在重复计算的问题。我尝试在Redux切片里创建Selector,但不知道怎么处理多ID数组的映射(只会处理单个字符串引用),希望得到更优的实现方案。

内容的提问来源于stack exchange,提问作者singlservinjack

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 13:41:40