1. ホーム
  2. javascript

[解決済み] Reduxはグローバルステートに過ぎないのか?

2023-03-30 22:32:24

疑問点

1週間前にReactを学び始めたのですが、必然的に状態の問題に行き着き、コンポーネントがどのようにアプリの残りの部分と通信することになっているのかに行き着きました。私は周りを検索し、Reduxは今月の味であるように思われます。ドキュメントをすべて読みましたが、実際にはかなり革命的なアイデアだと思います。以下は、それについての私の考えです。

状態は、一般に、かなり邪悪で、プログラミングのバグの大きな原因であると合意されています。Redux は、アプリケーション全体に分散させるのではなく、すべてをグローバルなステートツリーに集約して、それを変更するためにアクションを実行する必要がある、と言っています。面白そうですね。すべてのプログラムにはステートが必要だから、それをひとつの不純物のない空間に集めて、そこからしか変更できないようにすれば、バグの追跡が簡単になる。そして、個々の状態のピースを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;
}

これはまだ、放出されたアクションによって変化するグローバルなステートツリーですが、非常にシンプルで効率的です。

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

Reduxは単なるグローバルステートを美化したものではないのですか?

もちろんそうです。しかし、あなたがこれまで使ってきたすべてのデータベースについても同じことが言えます。Reduxをインメモリデータベースとして扱い、コンポーネントが反応的に依存できるようにする方がよいのです。

不変性によって、サブツリーが変更されたかどうかのチェックは、IDチェックまで単純化されるため、非常に効率的です。

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

React を使用している場合、最終的には実際の dom に対して diff を実行し、最小限のバッチ最適化された操作を実行しますが、完全なトップダウン再レンダリングはまだ非効率的です。

不変の木の場合、ステートレス コンポーネントは、依存するサブツリーが以前の値と比較して ID が異なるかどうかをチェックするだけでよく、もしそうならレンダリングを完全に回避することができます。