如何以最平坦的方式为 Redux 规范化对象数组?

How to normalize an array of objects in the flattest way for the Redux?

Beware! The question may be confusing and not relevant because my assumptions about the cause of the bug were wrong, the problem was in reducer, not in a way I represented a data.

So, the correct answer for the question is jpdelatorre’s one, but Joao’s is about the bug itself.

假设我有来自服务器的 JSON 响应,它是一个嵌套对象数组。如何将其展平,使商店处理尽可能简单?我试过像这样使用 normalizr 工具:

const imageSchema = new Schema('image', { idAttribute: 'id' });
const tooltipSchema = new Schema('tooltips', { idAttribute: 'id' });
imageSchema.define({
    tooltips: arrayOf(tooltipSchema),
});
const initData = data.map(item => normalize(item, imageSchema));

但我认为我做错了,因为它没有多大帮助。 store 仍然太复杂,因此我需要在 reducer 中使用一些递归的东西来更新状态。

此外,深度嵌套的状态使得使用 react-redux connect() 也非常困难,因为 it does only a shallow comparison.

响应的形状如下:

[
  {
    "id": 1,
    "title": "Partridge",
    "tooltips": [
      {
        "id": 10,
        "x": 0.56,
        "y": 0.59,
        "content": "Jacky"
      },
      {
        "id": 11,
        "x": 0.08,
        "y": 0.8,
        "content": "Sarah"
      }
    ]
  },
  {
    "id": 2,
    "title": "The Great Seal of South Australia",
    "tooltips": [
      {
        "id": 20,
        "x": 0.77,
        "y": 0.74,
        "content": "A sheaf of wheat"
      },
      {
        "id": 21,
        "x": 0.16,
        "y": 0.2,
        "content": "A sheep"
      }
    ]
  }
]

根据您的示例 here,您似乎在尝试修改状态(因此您遇到麻烦的原因是 redux 的浅层比较)。状态应该被视为不可变的,在你的减速器中返回的所有东西都应该是全新的对象。 Object.assign 修改第一个参数。

尝试替换 return Object.assign(state, { data: newEntities })

return Object.assign({}, state, { data: newEntities })

如果您坚持这样做,则不需要平面数据结构。

试试 normalizr

const imgSchema = new Schema('image', { idAttribute: 'id'});
const tooltipSchema = new Schema('tooltip');
imgSchema.define({
   tooltips: arrayOf(tooltipSchema)
});

const normalizedData = normalize(data, arrayOf(imgSchema));
console.log(normalizedData);

这将为您提供

的输出
{
   entities: {
      image: {
         1: {
            id: 1,
            title: 'Partride',
            tooltips: [10, 11]
         },
         2: {
            id: 2,
            title: 'The Great Seal...',
            tooltips: [20, 21]
         }
      },
      tooltips: {
          10: {
              id: 10,
              content: 'Jacky',
              x: 0.56,
              y: 0.59
          },
          ...
      }
   },
   result: [1, 2]
}

然后您可以将它保存到您的 redux 存储中。

您的问题是如何以最平坦的方式为 Redux 规范化对象数组?。我相信这是怎么做的。