web-dev-qa-db-ja.com

React-Reduxの複雑な(深い)状態オブジェクト

私の最初のredux状態は次のとおりです:

const state = {
  currentView: 'ROOMS_VIEW',
  navbarLinks: List([
    {name: 'Rooms', key: 'ROOMS_VIEW'},
    {name: 'Dev', key: ''}
  ]),
  roomListsSelected: {group: 0, item: 0},
  roomLists: [
    {
      name: "Filters",
      expanded: true,
      listItems: [
        { icon: 'images/icon-warning.svg', name: 'Alerts', filter: room => room.hasAlert },
        { icon: 'images/icon-playlist.svg', name: 'In Progress', filter: room => room.progress > 20 },
        { icon: 'images/icon-playlist.svg', name: 'Almost Done', filter: room => room.progress > 90 },
        { icon: 'images/icon-playlist.svg', name: 'Complete', filter: room => room.status === 'complete' },
        { icon: 'images/icon-playlist.svg', name: 'Recently Completed', filter: room => false },
        { icon: 'images/icon-playlist.svg', name: 'All Rooms', filter: room => true }
      ]
    }
  ],
  rooms: List(generateRooms())
}

これを行うレデューサーを作成する必要があります。

state.roomList[n].expanded = !state.roomList[n].expanded

Reduxワークフローを使用するのは初めてで、これを解決する最良の方法は、roomListをimmutable.jsオブジェクトにするか、コードを記述して状態オブジェクトのディープクローンを作成することです。

また、state.roomListには、将来の機能から新しいデータがプッシュされます。

Summery/Question:このように深い状態で変更を行う場合、Reducerで新しい状態オブジェクトを返す最良の方法は何ですか、またはRedux状態オブジェクトの構造を変更する必要がありますか?

私がやったこと最終的には不変は進むべき道のようです。 Immutableには、反応のレンダリング時間を短縮するいくつかのトリックがあり、すべてのプロジェクト要件を満たします。また、大きな変更を加えずに新しいライブラリを使用するには、プロジェクトの早い段階です。

30
Steven Bayer

まず、慣用的なReduxでは、状態を「正規化」して、可能な限り平坦化することをお勧めします。アイテムIDをキーとするオブジェクトを使用して、アイテムの直接検索を可能にし、IDの配列を使用して順序付けを示します。あるアイテムが別のアイテムを参照する必要がある場合は、実際のデータではなく他のアイテムのIDのみを保存します。これにより、ネストされたオブジェクトをより簡単に検索および更新できます。 Redux FAQネストされたデータに関する質問 を参照してください。

また、現在Redux状態で多くの関数を直接保存しているようです。 技術的にそれは機能しますが、それは間違いなく慣用的ではなく、タイムトラベルのデバッグのような機能を破壊するので、非常に推奨されません。 Redux FAQで詳細情報が得られます Redux状態にシリアル化できない値を保存するのは悪い考えです

編集:

フォローアップとして、最近 "Reducturing Reducers" のトピックに関する新しいセクションをReduxのドキュメントに追加しました。特に、このセクションには "状態形状の正規化" および "正規化データの更新" 、および "不変更新パターン" に関する章が含まれています。

50
markerikson

Reducer composition:レデューサーを単純なデータ構造に対応できるほど小さくするために、レデューサーを小さな断片に分解します。例えば。あなたの場合、あなたは以下を持っているかもしれません:roomListReducerlistItemsReducerlistItemReducer。次に、各レデューサーで、状態のどの部分を扱っているかをより簡単に読み取れるようにします。レデューサーはそれぞれ、「ディープコピーまたはシャローコピー」のようなことを心配する必要がない小さなデータを処理するため、非常に役立ちます。

Immutable私は個人的にimmutable.js私はプレーンなオブジェクトを扱うことを好むので。また、新しいAPIを採用するには変更するコードが多すぎます。しかし、考え方は、状態の変更が常に純粋な関数によって行われるようにすることです。したがって、単純に独自のヘルパー関数を記述して、必要なことを実行するだけで、複雑なオブジェクトを処理するときに徹底的にテストされることを確認できます。

または、簡単に言えば、各レデューサーで状態をいつでもディープコピーし、コピーを変更してからコピーを返すことができます。しかし、これは明らかに最善の方法ではありません。

6
xiaofan2406