リカバリステータス管理(Redux、Mobx、Recoil)


Reactにおいて、状態は、構成要素によって管理される動的情報(データ)である.ビューはステータスに応じてレンダリングされ、ステータスが変化すると、そのコンポーネントのビューも再レンダリングされ、置き換えられます.
react内のデータストリームは一方向であるため、コンポーネント管理データを부모 컴포넌트から자식 컴포넌트に転送することができるが、자식 컴포넌트=>부모 컴포넌트または자식 컴포넌트=>자식 컴포넌트で転送することは不可能である.

上記のように状態およびデータが伝達されると、サブコンポーネントの深さが大きいほど、状態管理が複雑になり、props drillingのような問題が発生する.これらの問題を解決するために現れたのはステータス管理ツールで、次のリストは典型的に使用されるツールの例です.
  • React Context
  • Redux
  • Mobx
  • Recoil
  • React Context


    React公式ドキュメントではcontextについて以下のように説明しています.
    context의 주된 용도는 다양한 레벨에 네스팅된 많은 컴포넌트에게 데이터를 전달하는 것입니다.
    主な目的は、異なるレベル、すなわち複数のサブコンポーネントにデータを伝達することによってprops drillingを防止することである.データの転送を継続するよりも、データをグローバルに共有して、データが必要なコンポーネントを検索して使用するだけです.中間層の素子はこれらのデータを知る必要はない.
    上記の利点により、propsドリルを使用しないで、より簡潔なコードを書くことができますが、react contextにはレンダリングに関連する致命的な欠点があります.次にその例を示します.
    // root 컴포넌트
    const App = () => {
      return (
        <AppProvider>
          <ComponentA />
          <ComponentB />
        </AppProvider>
      );
    }
    
    // 상태를 변경하는 컴포넌트
    const ComponentA = () => {
      const [, setData] = useContext(AppContext);
      const increase = () => {
      	setData((prevState) => prevState + 1);
      }
      return <button onClick={increase} />
    }
    
    // 상태를 가져와 렌더링하는 컴포넌트
    const ComponentB = () => {
      const [data] = useContext(AppContext);
      return <div>{`increased by: ${data}`}</div>
    }
    React contextを使用するには、Providerを使用してルート構成部品を囲む必要がありますが、AppContextのステータスが変更されると、プロバイダによって囲まれたすべての構成部品が再レンダリングされます.すなわち、ComponentAは、再レンダリングを必要とせずに状態のみを変更する構成要素であるが、状態が変化するにつれてComponentBとともに不要な再レンダリングとなる.上記の例では、2つの構成部品しかありませんが、contextを購読する構成部品が多いほど、レンダリングの問題が深刻になります.

    Redux


    Reduxは、世界の反応開発者が最もよく使用するステータス管理ライブラリです.Reduxはコンポーネントの外でグローバルにステータスを管理します.これはReactコンテキストと似ています.ただし、以下の点ではcontextとは異なる.
  • Reactだけでなく、Vanilla JS、Angular、Vueなどのフレームワークにも使用できます.
  • コンテキストは複数存在してもよく、Redux storeは1つしか存在しない.
  • のステータスが変更されても、すべての構成部品は再レンダリングされません.
  • ライブラリを使用して、
  • redux-saga、redux-thunk、およびredux-devtoolsなどの他の機能を提供できます.
  • Mobx


    Mobxは、Reduxなどのステータス管理ライブラリでもあり、クラス構成部品に基づいて作成され、オブジェクト向けのプログラミングでコードを記述することができます.したがって,Mobxと反応器の関数型素子のHooksを併用するとエラーが発生する可能性がある.
  • Mobxのobserver APIがクラス要素を返すため、Hooksは関数型要素でのみ使用できることを示すエラーが発生します.
  • mobx-react v 6またはmobx-react-liteを使用して、上記のエラーを必要とせずにhooksを使用します.
  • ボイラプレートコードなどを記述する必要があるReduxよりも楽です.
  • Mobx storeをグローバルオブジェクトとして使用すると、各コンポーネントからインポートして使用できますが、グローバルデータのコンポーネントアクセスを必要としないため、ユニットテストには適していません.したがって、Mobxの公式ドキュメントでは、context APIを使用して各コンポーネントからデータにアクセスすることを推奨します.
  • Recoil


    RecoilはRedux,Mobxとは異なり,Reactが提供する状態管理ライブラリである.ReduxとMobxはReactのライブラリではないため、React内部スケジューラにアクセスするのは難しい.最近、レコイルは동시성 모드を提供するために実験を行っており、レコイルが反応した状態を使用していることを示しているので、この機能もサポートできる.
  • 同期モード:各構成部品で実行される非同期要求を表示して判断するなどしてレンダリング優先度を決定し、レンダリングのモードを最適化します.レンダリングの準備ができたら、レンダリングを開始します.
  • Suspense:構成部品がレンダリングの準備ができていない場合は、レンダリングされず、サスペンス状態になります.fallbackアトリビュートを渡すと、次のようにレンダリングする構成部品を指定できます.
  • const Page = React.lazy(
      () =>  import('./Page);
    );
    
    <Suspense fallback={<WaitForPage />}>
      <Page />
    </Suspense>
    Recoilの利点は、他の状態管理ライブラリよりも軽く、React Contextに似ていることですが、最大の欠点は、不要なレンダリングの問題を回避できることです.Reactを作成したFacebookで作成したRecoilなので、これからもっと多くの機能がサポートされるかもしれません.

    参考資料


    「React公式文書」Context
    [応答文書]Suspense for Data Fetching(Experimental)
    ステータス管理ツールが必要
    ReactのMobxエクスペリエンス
    Context APIは存在するが、Reduxとグローバルステータス管理ライブラリがまだ使用されている理由
    Reactステータス管理ツールの使用と比較-(Redux VS MobX VS Context API)
    Recoil-別のレスポンスステータス管理ライブラリ?
    Recoilフォーミュラ:非同期アクション