web-dev-qa-db-ja.com

React、Flux、State、Stores

例のtodofluxアプリが少し不足していることがわかったので、学習して実験するためのアプリケーションを開発することで、頭を悩ませようとしています。

アプリケーションは、ドラッグアンドドロップのフルーツバスケットオーガナイザーです。私はいくつかのバスケットを持っており、それらの間にさまざまな果物をドラッグすることができます。果物をクリックするとハイライトでき、最後にドラッグしたアイテムはハイライトされたままになります。

これに基づいて、私は3つの店舗を持っています:

  • FruitStore
  • バスケットストア
  • AppStateStore-最後にクリックされた果物と最後にドラッグされた果物を追跡する

ユーザーアクションが発生すると、FruitActionがディスパッチされ、フルーツがクリックされた場合はAppStateStoreによって、フルーツが別のバスケットに移動された場合はすべてのストアによって処理されます。

メインのAppViewコンポーネントは、FruitStoreとAppStateStoreの両方からの変更イベントをリッスンして再レンダリングします。

私の質問は次のとおりです。

  • これはこのシナリオに適したアプローチですか?
  • AppViewは複数のストアをリッスンする必要がありますか? AppViewが連続して複数回レンダリングされないようにするにはどうすればよいですか?現在、フルーツが移動されると、FruitStoreとAppStateStoreの両方が変更イベントを発生させ、2つのレンダリングが連続して発生します。
  • ReactサイトのFluxの記事には、アクションオブジェクトをディスパッチするビュー(例:AppDispatcher.dispatch(TodoActions.updateText()))が示されていますが、アクションがそれ自体(例:FruitActionsのみ)をディスパッチした方がよいでしょう。 .moveBasket())およびAppViewはAppDispatcherを認識しませんか?
  • 現在、AppViewのみがストアをリッスンしますが、個々のFruitコンポーネントがAppStateStoreをリッスンして、強調表示される場合は自分自身のみを再レンダリングする必要がありますか?
  • Fluxアーキテクチャまたは同様のもののより完全な例はありますか?
19
user3687035
  • アプローチはかなり堅実に聞こえます。インタラクションごとにまったく異なるアクションを作成します。 FruitClickedFruitDraggedはどちらもアクションである可能性があり、ストアは気になるものを監視します。
  • AppViewは、データを取得するすべてのストアをリッスンする必要があります。同じティックでsetStateを複数回呼び出すと、Reactはそれらをインテリジェントにマージするため、実際に複数回レンダリングすることはありません。
  • Reactサイトの記事では、 セマンティックアクションの作成 の下で自分自身をディスパッチするアクションについて説明しています。コードブロックでは、ページをスクロールして長さを数回表示します。コード:

    _onDestroyClick: function() { 
      TodoActions.destroy(this.props.todo.id); 
    } 
    
  • この記事では、どのコンポーネントがストアをリッスンする必要があるかについても説明しています Controller-Viewで変更をリッスンする

    ストアの変更をリッスンするには、コンポーネント階層の最上位近くにReactコンポーネントが必要です。大規模なアプリでは、これらのリッスンコンポーネントがさらに多くなり、おそらくセクションごとに1つになります。 FacebookのAdsCreation Toolには、これらのコントローラーのようなビューが多数あり、それぞれがUIの特定のセクションを管理します。LookbackVideoEditorには、アニメーションプレビュー用と画像選択インターフェイス用の2つしかありませんでした。 。

    そして

    コンポーネントを単純に保つために、階層のより深いところにコントローラービューを追加する必要がある場合があります。これは、特定のデータドメインに関連する階層のセクションをより適切にカプセル化するのに役立つ場合があります。ただし、階層のより深いコントローラービューは、データフローに競合する可能性のある新しいエントリポイントを導入することにより、データの単一フローに違反する可能性があることに注意してください。深いコントローラービューを追加するかどうかを決定する際には、単純なコンポーネントのゲインと、さまざまなポイントで階層に流れる複数のデータ更新の複雑さのバランスを取ります。これらの複数のデータ更新は奇妙な効果をもたらす可能性があり、Reactのrenderメソッドが異なるコントローラービューからの更新によって繰り返し呼び出され、デバッグの難しさが増す可能性があります。

  • フラックスアーキテクチャに興味がある場合は、 Fluxxor (免責事項:私が書いた)に興味があるかもしれません。これは(うまくいけば)フラックスベースのアプリケーションの構築に役立ちます。これには、もう少し堅牢なディスパッチャーと、多くの場合に少し簡単にするためのその他のいくつかの変更(たとえば、非グローバルストア/アクション、Reactミックスイン)があります。
13
Michelle Tilley

アプリケーションをもう少し理解しなければ、このアプローチが優れているかどうかを判断するのは困難です。

ただし、果物のクリックはFruitStoreで処理する必要があるように思われます。つまり、果物はアクティブな状態になり、ドラッグ可能になりました。これがアプリケーション全体に何らかの影響を与える場合は、AppStateStoreにも変更が生じる可能性があります。同様に、あるバスケットから別のバスケットに果物を移動することは、BasketStoreのドメインのように見えます。

次のようなプライベートデータ構造を含むFruitStoreを想像します。

var _fruit = {
  1234: {
    id: '1234',
    type: 'Apple',
    active: false
  },
  2345: {
    id: '2345',
    type: 'orange',
    active: false
  },
  3456: {
    id: '3456',
    type: 'Apple',
    active: false
  }
};

そして、BasketStoreが次のようなプライベートデータ構造を持っていると想像します。

var _baskets = {
  4321: {
    id: '4321',
    name: 'Josephine\'s Basket',
    fruitIDs: [
      1234,
      2345
    ]
  },
  5432: {
    id: '5432',
    name: 'Harold\'s Basket',
    fruitIDs: [
      3456
    ]
  }
};

したがって、フルーツの「アクティブ」状態はFruitStoreによって管理され、バスケットの内容はBasketStoreによって管理されます。

したがって、これがアプリケーションで適切に機能する場合、AppViewは両方のストアをリッスンできます。また、前述のように、render()メソッドを繰り返し呼び出すコストはほとんどありません。これは、すべての呼び出しでDOMに影響を与えるわけではありません。これはReactの最大の強みの1つです。 Reactは、代わりに呼び出しをインテリジェントにバッチ処理し、DOMの「ダーティ」部分が存在する場合にのみ更新します。

ただし、バスケットをコントローラービューにすることもできます。フルーツをコントローラービューにすることを選択した場合は、componentWillUnmount()でリスナーをクリーンアップしてください。バスケットからバスケットへのフルーツの移動では、リスナーを破棄して再作成する必要がある場合があります。バスケットレベルで聞く方が理にかなっていると思いますが、繰り返しになりますが、あなたのアプリはよくわかりません。

最後の質問に答えるには:

Fluxアーキテクチャまたは同様のもののより完全な例はありますか?

Facebookのエンジニアは、waitFor()とサーバー側の永続ストレージの使用法を紹介するより複雑なアプリケーションの例に取り組んでいます。すぐにリリースしたいと思っています。

5
fisherwebdev