Redux: 反応成分をレデューサー内に保存することは大丈夫ですか?

作成日 2016年01月17日  ·  26コメント  ·  ソース: reduxjs/redux

やあ、

作業中のプロジェクトのレデューサー内にreactコンポーネントを格納しようとしています。 それが大丈夫かどうか、そしてどのようにアプローチすればよいか知りたいです。

私はそれをやろうとしましたが、レデューサー内のいくつかの機能が失われます。

反応コンポーネントは次のようになります。

{ function:
   { [Function: Connect]
     displayName: 'Connect(Counter)',
     WrappedComponent: { [Function: Counter] propTypes: [Object] },
     contextTypes: { store: [Object] },
     propTypes: { store: [Object] } } }

ただし、レデューサー内に保存すると、プロパティが失われ、次のようになります。

{ function:
   { [Function: Connect] } }

最も参考になるコメント

やりたいことは、いくつかのコンポーネントに一意の文字列IDを与え、それらのIDを状態に格納することです。 たとえば、次のような何かを保存可能性がModalTypes.LOGINstate.openModalId 、以降switchあなたの内側の<App>示すために、モーダルどのコンポーネントを選択するためのコンポーネントを。

全てのコメント26件

なぜそうする必要があるのか​​説明していただけますか?
ストアには、この状態を視覚的に表現するDOMコンポーネントではなく、シリアル化可能なアプリケーションの状態が含まれている必要があります。

絶対にしないでください。公式のアドバイスを参照してください。
何が州に行くべきではないのですか?

@simongfxu :+1:

明確化していただきありがとうございます@simongfxu

やりたいことは、いくつかのコンポーネントに一意の文字列IDを与え、それらのIDを状態に格納することです。 たとえば、次のような何かを保存可能性がModalTypes.LOGINstate.openModalId 、以降switchあなたの内側の<App>示すために、モーダルどのコンポーネントを選択するためのコンポーネントを。

@gaearonはい、私も同様の道を歩みました。 IDの代わりに名前(一意である必要があります)を保存しています。 次に、必要に応じて反応コンポーネントをrequireします。 コマンドでコンポーネントとレデューサーを有効にして無効にする必要があります。

この問題は解決されていることはわかっていますが、同様のユースケースがあるため、チャイムインしたいと思いました。

editorという名前のストアと、そのストアにactiveToolという名前のキーがあります。 このキーは文字列を保持し、正常に機能します。 ただし、 toolbarという名前のキーもあります。 このキーには、アクティブなツールでレンダリングする必要のあるコンポーネントクラスのリストを保持したいと思います。
私の行動は次のようなものです:

{
  type: 'SELECT_TOOL',
  payload: {
    name: 'toolName',
    tools: [A, List, Of, Tools]
  }
}

したがって、 editorレデューサーでは、このアクションをターゲットにして、次のようなことを行います(不変のjsを使用しますが、それはおそらく重要ではありません)。

return state
  .set('activeTool', payload.name)
  .set('toolBar', payload.tools)

ただし、dev-toolsは正しいactiveTool報告しますが、 toolBareditorストアから削除されています。 基本的に、OPと同じ症状。

とにかく、私は自分のユースケースをそこに出したかっただけです。
ストアでtoolBarプロパティを使用しなくなったので、ツールバーをレンダリングするコンポーネントに、ツール名をコンポーネントの配列にマップするオブジェクトがあります。

乾杯!

@ oscar-gシリアル化可能な(文字列または数値の)識別子をツールに割り当てる必要があります。これは、Reactコンポーネント自体ではなく、アクションを介して渡してストアに保存するものです。

ツール名をコンポーネントの配列にマップするオブジェクトがあります。

はい、これが唯一の方法です。

ありがとう、@ sompylasar。 それが基本的に私がやったことだと思います。

  1. action = {type: SELECT_TOOL, name: 'some string'}
  2. 名前を店に入れなさい。
  3. コンポーネントレンダリングの場合: return (TOOLMAP[this.props.tool.name])

TOOLMAPのキーがコンポーネントの配列にマップされる場所。 これは、コンポーネントファイル内の単なる定数です。

これはどういう意味ですか?

うん、これは行く方法です。

@simongfxuあなたのリンク「何が州に行くべきではないのですか?」 URIがなくなりました(新しいドキュメントにリダイレクトされます)。 リンクを更新してもらえますか? :)

@ Bartuz@ simongfxu :実際、新しいドキュメントにそのセクションと同等のものがあるかどうかは

Webアーカイブの元のページへのリンクは次のとおりです: React Docs:Interactivity and DynamicUIs 。 また、引用された元のコンテンツは次のとおりです。

州に行くべきではないことは何ですか?

this.stateは、UIの状態を表すために必要な最小限のデータのみを含める必要があります。 そのため、次のものを含めることはできません。

  • 計算されたデータ:状態に基づいて値を事前に計算する必要はありません。 render()内ですべての計算を行うと、UIの一貫性を確保するのが簡単になります。 たとえば、状態のリストアイテムの配列があり、カウントを文字列としてレンダリングする場合は、状態に保存するのではなく、 render()メソッドでthis.state.listItems.length + ' list items'をレンダリングするだけです。
  • Reactコンポーネント:基礎となる小道具と状態に基づいてrender()でコンポーネントをビルドします。
  • 小道具からの重複データ:可能な場合は、信頼できる情報源として小道具を使用するようにしてください。 小道具を状態で保存するための有効な使用法の1つは、小道具は時間の経過とともに変化する可能性があるため、以前の値を知ることができるようにすることです。

私の2セント:

  1. 現在のページのタイトル(ストア内の文字列に基づく)をレンダリングする単一のヘッダーコンポーネントを備えたモバイルアプリがあり、現在のページの特定のアクションボタン(編集、保存/キャンセル、アクション)がある場合とない場合があります>複数のアクションを含むドロップダウンなど)。 これは、ストアを介してコンポーネントを渡すためのユースケースになります。たとえば、各ページはヘッダー領域に独自のコンポーネントを「挿入」します。
  2. 上記のアプローチは、ReactとReduxが構築および最適化されたフローに反します。 ポータルは、必要に応じて魅力的な代替手段を提供しますが、その場合はストアをスキップします。 これは、監視/ロギングのニーズに応じて、良い場合と悪い場合があります。 Reduxを使用すると、文字列または文字列を含むオブジェクトでボタンを定義でき、「アクション」文字列でコンポーネントにリッスンさせることで動作をトリガーできます。

@Dindaleon公式のReactDocが示唆しているにもかかわらず、私はあなたの理解し、それが面白いと思います。

私も同様の問題を抱えています。 問題を開くことが良い考えかどうかわからない。

私は基本的に、プラグインを登録してUIに新しいコンポーネントを追加できるプラグインシステムを持っています。 私は現在、ストア内の「components」オブジェクトの下にそれらを追加しています。 これらはアクションクリエーターを使用して追加され、ペイロードキーの下を使用してそこに保存されます。 プラグインを追加できるUIコンポーネントは、何かが追加されているかどうかストアを確認するだけです。 はいの場合、そこからコンポーネントをプルしてレンダリングします。

ストアへの関数(レデューサー)/ reactコンポーネントの追加についてたくさん読んだことがあります。 しかし、私はこれに対する良い解決策を見つけることができませんでした。 コンパイル時に各要素を知る方法がないため、UI要素を実際にマップすることはできません。 そして、コアアプリケーションで新しいUI要素を利用できるようにするための登録メカニズムがどういうわけか必要です。

誰かが同じような状況にありましたか? どのようにそれらを解決しましたか? 私は、同様の問題を抱えている多くのオープンソースプロジェクトを調査しました(たとえば、アトム)。 それらは、コンポーネントをComponentStore (フラックス)内に格納します。

@SirWindfield :これを見たいと思うかもしれません: http//dylanpaulus.com/reactjs/2017/12/08/global-component-registration/ 。 これは、実行時にUIコンポーネントのルックアップを処理するためますが、手書きではなく、グローバルな変数と登録関数をテーブルに追加するように拡張されています。

アプリ全体で利用できるようにする必要がある場合は、Reactのcontextを使用して深くネストされたコンポーネントで利用できるようにする独自の<Provider>タイプのコンポーネントを作成することもできます。

@markerikson返信ありがとうございます!
これは実際、私が持っていたフラックスのアイデアにかなり近いように見えます:smile:
このトピックに関するリソースを見つけるのは非常に困難です。 一般的に、reduxとreactを使用してプラグインシステムを作成することに関心がないようです。

@SirWindfield :ええ、それは間違いなくあまり知られていないトピックです。

そうは言っても、 https://github.com/markerikson/redux-ecosystem-links/blob/master/component-state.md#modularity-and-encapsulationでいくつかの「Reduxplugin / encapsulation」タイプのライブラリをカタログ化しました。 私はまだそれらのどれかを自分で試す時間がありませんでした。 いつか彼らと一緒に実験して、彼らが何ができるのかを知りたいのですが、他にやることが多すぎます。 それでも、それらを調べて、ユースケースに一致するものがあるかどうかを確認することをお勧めします。

@markeriksonありがとう! このリストは素晴らしいです。

アップロード追跡の目的で、Fileオブジェクトを状態で保存したい場合はどうなりますか。 これは大丈夫ですか?

実際にはありません。シリアル化可能なオブジェクトしか保存できません。

ただし、ファイルのパスを保存することはできます

@albanxはい、可能性があります。ファイル(base64)をエンコードして、いつでも保存できます。 問題は、本当にファイルを保存する必要があるのか​​ということです。

@SirWindfield私はHTML5ファイルのBlobを意味しました(ユーザーがブラウザーでアップロードするファイルを選択したとき)。
@soulclownファイルのコンテンツは本当に必要ありませんが、File要素への参照だけが必要です。 アップローダーを作成していますが、アップロードされたファイルとその状態の進行状況を追跡したいと思います。 最終的にファイルのIDを作成し、その状態で保存します。

興味深いケース、アルバン。 これに対するあなたの解決策は何ですか?

[画像:メールトラック]
https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5&
送信者
によって通知された
メールトラック
https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5&
2018年8月1日、
15:12:04

2018-08-01 10:28 GMT + 02:00アルバン[email protected]

@SirWindfieldhttps ://github.com/SirWindfield私はHTML5ファイルを意味しました。
Blob(ユーザーがブラウザーでアップロードするファイルを選択したとき)。
@soulclownhttps ://github.com/soulclown私は本当に必要ありません
ファイルへのコンテンツですが、File要素への参照にすぎません。 わたし
アップローダーを作成し、アップロードされたファイルを追跡したい
状態の進歩。 最終的にファイルのIDを作成して保存します
状態でそれ。


あなたが言及されたのであなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/reduxjs/redux/issues/1248#issuecomment-409494273 、またはミュート
スレッド
https://github.com/notifications/unsubscribe-auth/AEL3RHZQT-Kp-MLFoUZryI0hrals0MFaks5uMWa8gaJpZM4HGj-F

FWIW、 @ markeriksonがプラグインフレームワークに関して示唆しているように、私はReactコンポーネント、レデューサー、ミドルウェアをreact-featuresおよびreact-redux-featuresパッケージとSSRを使用して、何年もの間redux状態で保存してきました。

Reactコンポーネントを含む状態ツリーの機能部分をシリアル化しないため、これは機能します。 SSR中にロードされた機能IDをシリアル化するだけです(これらは一意のグローバルID @gaearonです)
提案)。 しかし、私がコンセンサスから逸脱しているのは、クライアント側をブートストラップするときに、シリアル化できない部分を最初から再構築し、該当する機能IDのコンテンツをロードすることです。

1つの欠点は、タイムトラベルでは機能しないことです。 しかし、すべてのデバッグで、タイムトラベルデバッガーを切望していることに気づいたことはありません... reduxログで十分です。

シリアル化できない状態を、独自のコンテキストプロバイダーを使用して別の種類のストアに移動できると思います。 多分。 それは別のPITAかもしれませんが?

個別のグローバルコンポーネントとレデューサールックアップテーブルを使用すると、非同期チャンクの読み込みと調整するのがはるかに面倒になるため、この設計にたどり着きました。

このページは役に立ちましたか?
0 / 5 - 0 評価