我应该如何在 Redux 中深度复制状态数据?
How should I deep-duplicate state data in Redux?
我有几个状态实例,我需要在其中支持复制某些状态片段的操作。例如,我的产品是一个调查生成器,所以当我复制一个问题时,我也想复制它的答案,而不是让多个问题指向相同的答案实例。
状态归一化:
questionsById: {
q01: {
...
answers: ["a01"],
...
}
}
answersById: {
a01: {...}
}
在调度 QUESTION_DUPLICATE 的操作时,我还想复制任何答案。目前,我的 QUESTION_DUPLICATE 操作创建者还创建了新答案键的映射列表,然后答案缩减器使用它。
这种模式对我来说似乎很笨拙,尤其是在考虑更深层次重复的可能性时(例如,复制一个页面,其中包含问题,其中包含答案...)。深度复制归一化数据是否有更好的模式?
答案可能围绕着您通常如何处理规范化和非规范化数据。比如在我的博客post Practical Redux, Part 8: Form Draft Data Management, I reuse my existing normalization logic (which leverages the redux-orm library)复制一个要编辑的项目在我状态下的"current"和"draft"切片之间。因此,类似地,一种方法是对要复制的问题进行反规范化,然后重新对其进行规范化(在 action creator 或 reducer 中,视情况而定)。
我决定使用 normalizr 并且想出了一个递归复制器函数。它接受一个实体、模式和 keygen 函数,并通过给它们新的 id 递归地更新任何基于模式的嵌套实体。在基本情况下(当没有进一步的嵌套实体时)它将 return 更新其密钥的基本内容。
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;
这目前不支持 schema.Array
为数组中的多个实体类型设置 normalizr。我目前没有使用 schema.Array 并且这种情况下的支持非常重要,但我会在未来考虑它。
我有几个状态实例,我需要在其中支持复制某些状态片段的操作。例如,我的产品是一个调查生成器,所以当我复制一个问题时,我也想复制它的答案,而不是让多个问题指向相同的答案实例。
状态归一化:
questionsById: {
q01: {
...
answers: ["a01"],
...
}
}
answersById: {
a01: {...}
}
在调度 QUESTION_DUPLICATE 的操作时,我还想复制任何答案。目前,我的 QUESTION_DUPLICATE 操作创建者还创建了新答案键的映射列表,然后答案缩减器使用它。
这种模式对我来说似乎很笨拙,尤其是在考虑更深层次重复的可能性时(例如,复制一个页面,其中包含问题,其中包含答案...)。深度复制归一化数据是否有更好的模式?
答案可能围绕着您通常如何处理规范化和非规范化数据。比如在我的博客post Practical Redux, Part 8: Form Draft Data Management, I reuse my existing normalization logic (which leverages the redux-orm library)复制一个要编辑的项目在我状态下的"current"和"draft"切片之间。因此,类似地,一种方法是对要复制的问题进行反规范化,然后重新对其进行规范化(在 action creator 或 reducer 中,视情况而定)。
我决定使用 normalizr 并且想出了一个递归复制器函数。它接受一个实体、模式和 keygen 函数,并通过给它们新的 id 递归地更新任何基于模式的嵌套实体。在基本情况下(当没有进一步的嵌套实体时)它将 return 更新其密钥的基本内容。
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;
这目前不支持 schema.Array
为数组中的多个实体类型设置 normalizr。我目前没有使用 schema.Array 并且这种情况下的支持非常重要,但我会在未来考虑它。