如何在Redux中深度复制状态数据?

如何在Redux中深度复制状态数据?,redux,normalization,state-management,normalizr,Redux,Normalization,State Management,Normalizr,我有几个状态实例,需要支持复制某些状态片段的操作。例如,我的产品是一个调查生成器,因此当我复制一个问题时,我也希望复制它的答案,而不是让多个问题指向同一个答案实例 状态正常化: questionsById: { q01: { ... answers: ["a01"], ... } } answersById: { a01: {...} } 当发送问题_replicate的操作时,我还想复制任何答案。目前,my QUESTION_DUPLICATE actio

我有几个状态实例,需要支持复制某些状态片段的操作。例如,我的产品是一个调查生成器,因此当我复制一个问题时,我也希望复制它的答案,而不是让多个问题指向同一个答案实例

状态正常化:

questionsById: {
  q01: {
    ...
    answers: ["a01"],
    ...
  }
}
answersById: {
  a01: {...}
}
当发送问题_replicate的操作时,我还想复制任何答案。目前,my QUESTION_DUPLICATE action creator还创建了一个新答案键的映射列表,然后答案缩减器将使用该列表


这种模式对我来说似乎很难实现,尤其是考虑到可能会出现更深层次的复制(例如,复制包含问题和答案的页面…)。是否有更好的模式可以深度复制规范化数据?

答案可能围绕您通常如何处理数据的规范化和非规范化。例如,在我的博客文章中,我重用现有的规范化逻辑(利用库)在我的状态的“当前”和“草稿”切片之间复制要编辑的项。因此,类似地,一种方法是将要复制的问题反规范化,然后重新规范化(在action creator或reducer中,如您所见)。

我决定使用Normalizer,我提出了一个递归复制器函数。它接受一个实体、模式和keygen函数&通过给嵌套实体提供新的id,基于模式递归地更新它们。在基本情况下(当没有更多的嵌套实体时),它将返回其键已更新的基本内容

const duplicator = (entity, schema, keygen) => {
    const newEntity = {
            ...entity,
            [schema._idAttribute]: keygen(entity, schema)
    };
    if (Object.keys(schema.schema).length === 0) {
            return newEntity;
    }
    return Object.keys(schema.schema).reduce(
            (acc, nestedKey) => {
                    if (!entity.hasOwnProperty(nestedKey)) {
                            return acc;
                    }
                    if (!Array.isArray(schema.schema[nestedKey])) {
                            return {
                                    ...acc,
                                    [nestedKey]: duplicator(
                                            entity[nestedKey],
                                            schema.schema[nestedKey],
                                            keygen
                                    )
                            };
                    }
                    return {
                            ...acc,
                            [nestedKey]: acc[nestedKey].map((nestedEntity, index) =>
                                    duplicator(nestedEntity, schema.schema[nestedKey][0], keygen)
                            )
                    };
            },
            { ...newEntity }
    );
};

export default duplicator;
这目前不支持为数组中的多个实体类型设置normalizer。我目前不使用Schema.Read,这种情况很不需要支持,但我以后会考虑它。

GoTCHA-我仍然把事情放在一起,所以我还没有确定一个归一化策略,所以我将把它作为一个信号,我应该开始这样做: