状态为对象数组与由id键入的对象 [英] State as array of objects vs object keyed by id

查看:123
本文介绍了状态为对象数组与由id键入的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

设计状态形状的章节中,文档建议保留在由ID键入的对象中的状态:

In the chapter on Designing the State Shape, the docs suggest to keep your state in an object keyed by ID:


保持以ID作为键存储的对象中的每个实体,并使用ID引用来自其他实体或列表。

Keep every entity in an object stored with an ID as a key, and use IDs to reference it from other entities, or lists.

他们继续陈述


将应用程序的状态视为数据库。

Think of the app’s state as a database.

我正在研究状态形状过滤器列表,其中一些将打开(它们显示在弹出窗口中),或者具有选定的选项。当我读到将应用程序的状态视为数据库时,我考虑将它们视为JSON响应,因为它将从API(本身由数据库支持)返回。

I'm working on the state shape for a list of filters, some of which will be open (they're displayed in a popup), or have selected options. When I read "Think of the app’s state as a database," I thought about thinking of them as a JSON response as it would be returned from an API (itself backed by a database).

所以我认为它是

[{
    id: '1',
    name: 'View',
    open: false,
    options: ['10', '11', '12', '13'],
    selectedOption: ['10'],
    parent: null,
  },
  {
    id: '10',
    name: 'Time & Fees',
    open: false,
    options: ['20', '21', '22', '23', '24'],
    selectedOption: null,
    parent: '1',
  }]

但是,文档建议格式更多喜欢

However, the docs suggest a format more like

{
   1: { 
    name: 'View',
    open: false,
    options: ['10', '11', '12', '13'],
    selectedOption: ['10'],
    parent: null,
  },
  10: {
    name: 'Time & Fees',
    open: false,
    options: ['20', '21', '22', '23', '24'],
    selectedOption: null,
    parent: '1',
  }
}

理论上,它只要数据可序列化(在州标题下)就无所谓。

In theory, it shouldn't matter as long as the data is serializable (under the heading "State").

所以我快乐地采用了对象阵列方法,直到我写了我的减速器。

So I went with the array-of-objects approach happily, until I was writing my reducer.

使用object-keyed-by-id方法(并自由使用扩展语法),reducer的 OPEN_FILTER 部分变为

With the object-keyed-by-id approach (and liberal use of the spread syntax), the OPEN_FILTER part of the reducer becomes

switch (action.type) {
  case OPEN_FILTER: {
    return { ...state, { ...state[action.id], open: true } }
  }

采用对象数组方法,它是更详细的(和辅助函数依赖)

Whereas with the array-of-objects approach, it's the more verbose (and helper function reliant)

switch (action.type) {
   case OPEN_FILTER: {
      // relies on getFilterById helper function
      const filter = getFilterById(state, action.id);
      const index = state.indexOf(filter);
      return state
        .slice(0, index)
        .concat([{ ...filter, open: true }])
        .concat(state.slice(index + 1));
    }
    ...



所以我的问题有三个:



1)减速器的简单性是否采用对象键控id方法的动机?该州的形状还有其他优势吗?

So my questions are threefold:

1) Is the simplicity of the reducer the motivation for going with the object-keyed-by-id approach? Are there other advantages to that state shape?

2)似乎对象键入 - by-id方法使得处理API的标准JSON输入/输出变得更加困难。 (这就是我首先使用对象数组的原因。)因此,如果你采用这种方法,你是否只使用一个函数在JSON格式和状态形状格式之间来回转换它?这看起来很笨拙。 (虽然如果你提倡这种方法,你的推理是否比上面的对象数组减少器更少笨重?)

2) It seems like the object-keyed-by-id approach makes it harder to deal with standard JSON in/out for an API. (That's why I went with the array of objects in the first place.) So if you go with that approach, do you just use a function to transform it back and forth between JSON format and state shape format? That seems clunky. (Though if you advocate that approach, is part of your reasoning that that's less clunky than the array-of-objects reducer above?)

3)我知道Dan Abramov将redux设计为理论上与状态数据结构无关(正如按照惯例,顶级状态是一个对象或一些其他键值集合,如Map,但从技术上讲,它可以是任何类型强调我的)。但鉴于上述情况,是否只是建议将其保持为ID键入的对象,或者是否存在其他无法预料的痛点,我将通过使用一系列对象来解决这个问题,这样我就应该中止计划并尝试坚持使用ID键入的对象?

3) I know Dan Abramov designed redux to theoretically be state-data-structure agnostic (as suggested by "By convention, the top-level state is an object or some other key-value collection like a Map, but technically it can be any type," emphasis mine). But given the above, is it just "recommended" to keep it an object keyed by ID, or are there other unforeseen pain points I'm going to run into by using an array of objects that make it such that I should just abort that plan and try to stick with an object keyed by ID?

推荐答案

Q1:减速器的简单性是由于没有搜索数组以找到正确的条目。不必搜索阵列是有利的。选择器和其他数据访问器可能并且经常通过 id 访问这些项目。必须在阵列中搜索每次访问都会成为性能问题。当阵列变大时,性能问题会急剧恶化。此外,随着您的应用变得更加复杂,在更多地方显示和过滤数据,问题也会恶化。这种组合可能是有害的。通过 id 访问项目,访问时间从 O(n)变为 O (1),对于大的 n (这里是数组项)会有很大的不同。

Q1: The simplicity of the reducer is a result of not having to search through the array to find the right entry. Not having to search through the array is the advantage. Selectors and other data accessors may and often do access these items by id. Having to search through the array for each access becomes a performance issue. When your arrays get larger, the performance issue worsens steeply. Also, as your app becomes more complex, showing and filtering data in more places, the issue worsens as well. The combination can be detrimental. By accessing the items by id, the access time changes from O(n) to O(1), which for large n (here array items) makes a huge difference.

Q2:您可以使用 normalizr 帮助您从API到商店的转换。从normalizr V3.1.0开始,你可以使用denormalize来反过来。也就是说,应用程序通常比数据生产者更多的消费者,因此转换到商店通常会更频繁地进行。

Q2: You can use normalizr to help you with the conversion from API to store. As of normalizr V3.1.0 you can use denormalize to go the other way. That said, Apps are often more consumers than producers of data and as such the conversion to store is usually done more frequently.

问题3:您将遇到的问题使用数组不是存储惯例和/或不兼容问题,而是更多的性能问题。

Q3: The issues you'll run into by using an array are not so much issues with the storage convention and/or incompatibilities, but more performance issues.

这篇关于状态为对象数组与由id键入的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆