web-dev-qa-db-ja.com

Reduxはグローバルな状態を単に美化しただけではありませんか?

だから、私はReact 1週間前に学習を始めました。私は必然的に状態の問題と、コンポーネントがアプリの他の部分と通信する方法を理解しました。私はすべてのドキュメントを読んで、それは実際にはかなり革命的なアイデアだと思います。

状態は一般に、かなり悪であり、プログラミングのバグの大きな原因であることに同意しています。アプリ全体に散らばるのではなく、Reduxは、変更するためにアクションを発行する必要があるグローバルな状態ツリーにすべてを集中させないのはなぜかと言います。興味深いですね。すべてのプログラムには状態が必要なので、バグを簡単に追跡できるように、1つの不純なスペースに固定して、そこから変更するだけにします。次に、個々の状態ピースをReactコンポーネントに宣言的にバインドし、それらを自動再描画してすべてが美しいようにすることもできます。

ただし、この設計全体について2つの質問があります。 1つには、なぜ状態ツリーが不変である必要があるのですか?タイムトラベルのデバッグ、ホットリロードは気にせず、既にアプリに元に戻す/やり直しを実装しているとします。これをしなければならないのはとても面倒です。

case COMPLETE_TODO:
  return [
    ...state.slice(0, action.index),
    Object.assign({}, state[action.index], {
      completed: true
    }),
    ...state.slice(action.index + 1)
  ];

これの代わりに:

case COMPLETE_TODO:
  state[action.index].completed = true;

言うまでもなく、学習するためだけにオンラインホワイトボードを作成しています。すべての状態変更は、コマンドリストにブラシストロークを追加するのと同じくらい簡単です。しばらくすると(数百のブラシストローク)この配列全体を複製すると、非常に高価で時間がかかるようになります。

アクションを介して変更されるUIから独立したグローバル状態ツリーで問題ありませんが、本当に不変である必要がありますか?このような単純な実装の何が問題になっていますか(非常に大まかなドラフト。1分で書きました)。

var store = { items: [] };

export function getState() {
  return store;
}

export function addTodo(text) {
  store.items.Push({ "text": text, "completed", false});
}

export function completeTodo(index) {
  store.items[index].completed = true;
}

まだ実行されたアクションによって変更されたグローバル状態ツリーですが、非常にシンプルで効率的です。

73
Ryan Peschel

Reduxはグローバルな状態を単に美化しただけではありませんか?

もちろん。ただし、これまでに使用したすべてのデータベースに同じことが当てはまります。 Reduxは、コンポーネントが事後的に依存できるインメモリデータベースとして扱う方が適切です。

不変性は、サブツリーが同一性チェックまで簡素化されるため、サブツリーが非常に効率的に変更されたかどうかのチェックを可能にします。

はい、実装は効率的ですが、ツリーが何らかの形で操作されるたびに仮想dom全体を再レンダリングする必要があります。

Reactを使用している場合、最終的に実際のDOMに対して差分を作成し、最小限のバッチ最適化操作を実行しますが、完全なトップダウン再レンダリングは依然として非効率的です。

不変ツリーの場合、ステートレスコンポーネントは、依存するサブツリーが以前の値と比較して同一であるかどうかを確認する必要があります。そうであれば、レンダリングを完全に回避できます。

44
lorefnon