1. ホーム
  2. javascript

[解決済み] オブジェクトの配列としての状態 vs. idをキーとしたオブジェクトの状態

2022-12-21 02:14:58

疑問点

の章では ステートシェイプの設計 の章では、IDをキーとするオブジェクトに状態を保持することが提案されています。

IDをキーとして保存されたオブジェクトにすべてのエンティティを保持し、他のエンティティやリストからそれを参照するためにIDを使用します。

彼らは続けて次のように述べています。

<ブロッククオート

アプリの状態をデータベースと考えましょう。

私はフィルターのリストの状態形状に取り組んでおり、そのうちのいくつかは開いている (ポップアップで表示される)、または選択されたオプションを持っています。アプリの状態をデータベースとして考える」を読んで、API (それ自体がデータベースによってバックアップされる) から返される JSON 応答としてそれらを考えることについて考えました。

というように考えていました。

[{
    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',
  }]

しかし、ドキュメントによると

{
   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',
  }
}

理論上は のデータがシリアライズ可能である限り、問題にはならないはずです(見出し "State"の下)。 .

というわけで、Reducerを書くまでは、喜んでarray-of-objectsのアプローチで行っていました。

オブジェクト・キー・バイ・IDのアプローチ(およびスプレッド構文の自由な使用)で OPEN_FILTER の部分は

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

一方、array-of-objectsのアプローチでは、より冗長な(そしてヘルパー関数に依存する)ものである。

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));
    }
    ...

そこで、質問は3つあります。

1) Reducer のシンプルさは、object-keyed-by-id アプローチを採用する動機となりますか?その状態の形状に他の利点がありますか?

そして

2) Object-keyed-by-id のアプローチでは、API のための標準的な JSON in/out を扱うのが難しくなるように思えます。(その場合、JSON形式とstate shape形式を行き来するための関数を使うだけなのでしょうか?(そのアプローチを提唱する場合、その理由の一部は、上記のオブジェクトの配列のリデューサよりも不格好ではないということでしょうか?)

そして

3) Dan Abramov が redux を理論的には状態-データ-構造にとらわれないように設計したことは知っています (これは "慣習上、トップレベルの状態はオブジェクトやMapのようなキーバリューのコレクションですが 技術的には任意の型にすることができます。 ," を強調しています)。それとも、オブジェクトの配列を使用することによって、その計画を中止して、IDによってキーが設定されたオブジェクトに固執しようとするような、予期しないペインポイントがあるのでしょうか?

どのように解決するのですか?

Q1: リデューサがシンプルなのは、配列の中から正しいエントリを探す必要がないためです。配列の中を探さなくてよいというのは利点です。セレクタや他のデータアクセサは、これらの項目に対して id . アクセスのたびに配列内を検索しなければならないのは、性能上の問題となります。配列が大きくなると、パフォーマンスの問題は急激に悪化します。また、アプリケーションがより複雑になり、より多くの場所でデータを表示したりフィルタリングしたりするようになると、この問題も悪化します。この組み合わせは不利になりかねません。アイテムにアクセスする際に id でアクセスすると、アクセス時間が O(n) から O(1) であり、大きな n (ここでは配列項目)では大きな違いになります。

Q2:このような場合は normalizr を使うと、APIからストアへの変換を助けることができます。normalizr V3.1.0の時点では、他の方法に行くためにdenormalizeを使用することができます。とはいえ、アプリはデータの生産者よりも消費者が多く、そのためストアへの変換は通常より頻繁に行われます。

Q3: 配列を使用することで発生する問題は、ストレージの規約や非互換性の問題ではなく、パフォーマンスの問題だと思うのですが。