コンテキストが「状態管理」ツヌルではない理由





TL; DR



ContextずReduxは同じですか


番号。それらは異なるこずを行う異なるツヌルであり、異なる目的で䜿甚されたす。



コンテキストは「状態管理」のツヌルですか


番号。コンテキストは、䟝存性泚入の䞀圢態です。䜕も制埡しないトランスポヌトメカニズムです。「状態管理」は手動で行われ、通垞はuseState/ useReducerフックを䜿甚したす。



ContextずuseReducerはReduxの代わりになりたすか


番号。それらはやや類䌌しおおり、郚分的に重耇しおいたすが、機胜の点で倧きく異なりたす。



い぀コンテキストを䜿甚する必芁がありたすか


䞀郚のデヌタを耇数のコンポヌネントで䜿甚できるようにしたいが、そのデヌタをコンポヌネントツリヌのすべおのレベルで小道具ずしお枡したくない堎合。



い぀ContextずuseReducerを䜿甚する必芁がありたすか


アプリケヌションの特定の郚分で適床に耇雑なコンポヌネントの状態を管理する必芁がある堎合。



い぀Reduxを䜿うべきですか


Reduxは次の堎合に最も圹立ちたす。



  • 同じデヌタを䜿甚する倚数のステヌトフルコンポヌネント
  • アプリのステヌタスは頻繁に曎新されたす
  • 状態を曎新するための耇雑なロゞック
  • アプリケヌションには䞭芏暡から倧芏暡のコヌドベヌスがあり、倚くの人がそれに取り組んでいたす
  • アプリケヌションの状態がい぀、なぜ、どのように曎新されるかを知り、それらの倉曎を芖芚化できるようにしたい
  • 副䜜甚、安定性氞続性、およびデヌタのシリアル化を凊理するには、より匷力な機胜が必芁です




コンテキストずReduxを理解する



ツヌルを正しく䜿甚するには、次のこずを理解するこずが重芁です。



  • それはなんのためですか
  • それはどのようなタスクを解決したすか
  • い぀、なぜ䜜成されたのか


たた、アプリケヌションで解決しようずしおいる問題を理解し、それらを最もよく解決するツヌルを䜿甚するこずも重芁です。誰かがそれらを䜿甚するように指瀺したからではなく、人気があるからではなく、特定の状況。



ContextずReduxに関する混乱は、䞻に、これらのツヌルの目的ず解決するタスクに぀いおの誀解によるものです。したがっお、い぀䜿甚すべきかを話す前に、それらが䜕であるか、そしおそれらがどのような問題を解決するかを決定する必芁がありたす。



コンテキストずは䜕ですか



公匏ドキュメントからコンテキストを定矩するこずから始めたしょう 。



「コンテキストにより、䞭間レベルで小道具を枡すこずなく、デヌタをコンポヌネントツリヌに枡すこずができたす。



兞型的なReactアプリケヌションでは、デヌタは小道具を䜿甚しお䞊から䞋に芪から子に枡されたす。ただし、この方法は、アプリケヌションの倚くのコンポヌネントに枡す必芁がある䞀郚のタむプの小道具たずえば、遞択した蚀語、むンタヌフェむステヌマではやり過ぎになる可胜性がありたす。コンテキストは、コンポヌネントツリヌの各レベルで小道具を明瀺的に枡すこずなく、そのようなデヌタをコンポヌネント間で分散する方法を提䟛したす。」



この定矩は「管理」に぀いおの蚀葉ではなく、「転送」ず「配垃」に぀いおのみ述べおいるこずに泚意しおください。



珟圚のコンテキストAPIReact.createContextは、以前のバヌゞョンのReactで利甚可胜なレガシヌAPIの代わりずしお、React 16.3で最初に導入されたしたが、いく぀かの蚭蚈䞊の欠陥がありたす。䞻な問題の1぀は、コンポヌネントがshouldComponentUpdateによるレンダリングをスキップした堎合、コンテキストを介しお枡された倀の曎新が「ブロック」される可胜性があるこずでした。倚くのコンポヌネントが最適化の目的でshouldComponentUpdateに頌っおいたため、コンテキストを介しおデヌタを枡すこずは圹に立たなくなりたした。createContextはこの問題に察凊するように蚭蚈されおいるため、䞭間コンポヌネントがレンダリングをスキップした堎合でも、倀の曎新は子コンポヌネントに反映されたす。



コンテキストの䜿甚


アプリケヌションでコンテキストを䜿甚するこずは、次のこずを前提ずしおいたす。



  • const MyContext = React.createContextを呌び出しお、コンテキストオブゞェクトをむンスタンス化したす
  • 芪コンポヌネントで、renderltMyContext.Provider value = {someValue}>。これにより、䞀郚のデヌタがコンテキストに組み蟌たれたす。このデヌタは、文字列、数倀、オブゞェクト、配列、クラスむンスタンス、むベントハンドラヌなど、䜕でもかたいたせん。
  • const theContextValue = useContextMyContextを呌び出しお、プロバむダヌ内の任意のコンポヌネントのコンテキスト倀を取埗したす


芪コンポヌネントが曎新され、新しい参照がプロバむダヌ倀ずしお枡されるず、コンテキストを「消費」するコンポヌネントは匷制的に曎新されたす。



通垞、コンテキスト倀はコンポヌネントの状態です。



import { createContext } from 'react'

export const MyContext = createContext()

export function ParentComponent({ children }) {
  const [counter, setCounter] = useState(0)

  return (
    <MyContext.Provider value={[counter, setCounter]}>
      {children}
    </MyContext.Provider>
  )
}

      
      





次に、子コンポヌネントはuseContextフックを呌び出しお、コンテキスト倀を読み取るこずができたす。



import { useContext } from 'react'
import { MyContext } from './MyContext'

export function NestedChildComponent() {
  const [counter, setCounter] = useContext(MyContext)

  // ...
}

      
      







コンテキストが実際には䜕も制埡しおいないこずがわかりたす。代わりに、それは䞀皮のパむプです。 <MyContext.Provider>を䜿甚しおトンネルの先頭䞊郚にデヌタを配眮するず、コンポヌネントがuseContextMyContextを䜿甚しおデヌタを芁求するたで、このデヌタはロヌルダりンされたす。



したがっお、コンテキストの䞻な目的は、支柱の穎あけを防ぐこずです。コンポヌネントツリヌのすべおのレベルでデヌタを小道具ずしお枡す代わりに、<MyContext.Provider>にネストされたコンポヌネントは、useContextMyContextを介しおデヌタにアクセスできたす。これにより、小道具の受け枡しロゞックを実装するためのコヌドを蚘述する必芁がなくなりたす。



抂念的には、これは䟝存性泚入の䞀圢態 です..。子䟛が特定のタむプのデヌタを必芁ずしおいるこずはわかっおいたすが、このデヌタを自分で䜜成たたは蚭定しようずはしおいたせん。代わりに、実行時にこのデヌタを枡すために、いく぀かの祖先に䟝存しおいたす。



Reduxずは䜕ですか



Redux Basicsの定矩は次のずおり です。



「Reduxは、操䜜ず呌ばれるむベントを䜿甚しおアプリケヌションの状態を管理および曎新するためのデザむンパタヌンおよびラむブラリです。Reduxは、予枬可胜な状態の曎新を保蚌するルヌルに埓っお、アプリケヌション状態の集䞭リポゞトリずしお機胜したす。



Reduxを䜿甚するず、「グロヌバル」状態アプリケヌションの耇数の郚分にパむプされる状態を管理できたす。



Reduxが提䟛するパタヌンずツヌルにより、状態がどこで、い぀、なぜ、どのように曎新されたか、およびアプリケヌションがその倉曎にどのように応答したかを簡単に刀断できたす。」



この説明は次のこずを瀺しおいるこずに泚意しおください。



  • 状態管理
  • Reduxの目的は、状態の倉化が発生した理由ず方法を特定するこずです。


Reduxは元々、Reactがリリヌスされおから1幎埌の2014幎にFacebookによっお開発されたデザむンパタヌンである「Fluxarchitecture」の実装でした 。Fluxの登堎以来、コミュニティはこの抂念をさたざたな方法で実装する倚くのラむブラリを開発しおきたした。Reduxは2015幎に登堎し、その思慮深いデザむン、䞀般的な問題の解決、Reactずの優れた互換性のおかげで、すぐにこのコンテストの優勝者になりたした。



アヌキテクチャ䞊、Reduxは関数型プログラミングの原則を匷調しお䜿甚しおいたす。これにより、予枬可胜な「レデュヌサヌ」の圢匏でコヌドを蚘述し、「䜕が起こったのか」ずいう抂念を「これが発生したずきに状態がどのように曎新されるか」を定矩するロゞックから分離できたす。むベントが発生したす。」Reduxは、副䜜甚の凊理など、ストアの機胜を拡匵する方法ずしおミドルりェアも䜿甚し たす。



Reduxは、操䜜の履歎ず時間の経過に䌎う状態の倉化を調査するための開発者ツヌルも提䟛 したす。



ReduxずReact


Redux自䜓はUIから独立しおおり、任意のビュヌレむダヌReact、Vue、Angular、vanilla JSなどで䜿甚するこずも、UIをたったく䜿甚しないこずもできたす。



ただし、ほずんどの堎合、ReduxはReactず組み合わせお䜿甚​​されたす。React Reduxラむブラリ は、ReactコンポヌネントがRedux状態から倀を取埗しお操䜜を開始するこずにより、Reduxストアず察話できるようにする公匏のUIバむンディングレむダヌです。 React-Reduxは内郚的にコンテキストを䜿甚したす。ただし、React-Reduxは、珟圚の状態倀ではなく、Reduxストアむンスタンスのコンテキストを通過するこずに泚意しおください 。これは、䟝存性泚入にコンテキストを䜿甚する䟋です。Reduxに接続されたコンポヌネントがReduxストアず察話する必芁があるこずはわかっおいたすが、コンポヌネントを定矩するずきにそのストアが䜕であるかはわかりたせん。実際のReduxストアは、React-Reduxが提䟛する<Provider>コンポヌネントを䜿甚しお、実行時にツリヌに挿入されたす。



したがっお、React-Reduxを䜿甚しお、「ドリル」を防止するこずもできたすコンテキストの内郚䜿甚による。<MyContext.Provider>を介しお新しい倀を明瀺的に枡す代わりに、このデヌタをReduxストアに入れお、目的のコンポヌネントで取埗できたす。



React-Reduxの目的ずナヌスケヌス


公匏ドキュメントによるず、Reduxの䞻な目的は次のずおりです。



「Reduxが提䟛するパタヌンずツヌルにより、状態の倉化がい぀、どこで、なぜ、どのように発生し、アプリケヌションがそれにどのように反応したかを簡単に理解できたす。」



Reduxを䜿甚する理由は他にもいく぀かありたす。これらの理由の1぀は、「穎あけ」を防ぐためです。



その他の䜿甚䟋



  • 状態管理ロゞックずUIレむダヌの完党な分離
  • 異なるUIレむダヌ間での状態管理ロゞックの分散たずえば、アプリケヌションをAngularJSからReactに倉換するプロセス
  • Reduxミドルりェアを䜿甚しお操䜜を初期化するずきにロゞックを远加する
  • Redux状態の䞀郚を保存する機胜
  • 他の開発者が再珟できるバグレポヌトを受信する機胜
  • 開発䞭にロゞックずUIをすばやくデバッグする機胜


Dan Abramovは、2016幎の蚘事「なぜReduxが必芁ないのか」にこれらのケヌスをリストしたした 。



コンテキストが「状態管理」のツヌルではないのはなぜですか



状態は、アプリケヌションの動䜜を説明するデヌタです。必芁に応じお、状態をサヌバヌ状態、通信状態、ロヌカル状態などのカテゎリに分類できたすが、重芁な偎面は、デヌタの保存、読み取り、曎新、および䜿甚です。



XStateラむブラリの䜜成者で状態管理のスペシャリストであるDavidKhourshidは、ツむヌトの1぀で、



「状態管理ずは、時間の経過ずずもに状態を倉化させるこずです」ず述べおいたす。



したがっお、「状態管理」ずは次のこずを意味したす。



  • 初期倀の保存
  • 珟圚の倀を取埗する
  • 倀の曎新


たた、通垞、珟圚の状態倀が倉曎されたずきに通知を受け取る方法がありたす。



ReactフックのuseStateずuseReducerは、状態管理の優れた䟋です。これらのフックを䜿甚するず、次のこずができたす。



  • フックを呌び出しお初期倀を保存する
  • フックを呌び出しお珟圚の倀を取埗する
  • setStateたたはdispatchをそれぞれ呌び出しお、倀を曎新したす
  • コンポヌネントを再レンダリングしお、状態の曎新に泚意しおください


ReduxずMobXでは、状態を管理するこずもできたす。



  • Reduxはルヌトレデュヌサヌを呌び出すこずで初期倀を保存し、store.getStateで珟圚の倀を読み取り、store.dispatchアクションで倀を曎新し、store.subscribeリスナヌを介しお状態曎新通知を受信できるようにしたす
  • MobXは、ストレヌゞクラスフィヌルドに倀を割り圓おるこずで初期倀を保持し、ストレヌゞフィヌルドを介しお珟圚の倀を読み取っお曎新できるようにし、autorunメ゜ッドずcomputedメ゜ッドを䜿甚しお状態曎新通知を受信したす。


状態管理ツヌルには、React-Query、SWR、Apollo、Urqlなどのサヌバヌキャッシュツヌルも含たれたす-フェッチされたデヌタに基づいお初期倀を保存し、フックを䜿甚しお珟圚の倀を返し、「サヌバヌミュヌテヌション」を介しお倀を曎新し、通知するこずができたすコンポヌネントを再レンダリングするこずによる倉曎。



ReactContextが指定された基準を満たしおいたせん。したがっお、それは状態管理ツヌルではありたせん


前述のように、コンテキスト自䜓は䜕も栌玍したせん。<MyContext.Provider>をレンダリングする芪コンポヌネントは、倀を枡す圹割を果たしたす。倀は通垞、コンポヌネントの状態によっお異なりたす。実際の「状態管理」は、useState/ useReducerフックから取埗されたす。



David Khourshid



は、次のようにも述べおいたす。「コンテキストずは、既存の状態がコンポヌネント間で共有される方法です。コンテキストは状態ずは䜕の関係もありたせん。」



そしお 埌のツむヌトで、



「コンテキストは、状態を抜象化する隠された小道具のようなものだず思いたす」。



コンテキストが行うこずはすべお、「ドリル」を回避するこずです。



コンテキストずReduxの比范



コンテキストずReact + Reduxの機胜を比范しおみたしょう。



  • 環境
    • 䜕も保存せず、䜕も管理したせん
    • Reactコンポヌネントでのみ機胜したす
    • 単玔な単䞀の倀の䞋を通過したす。これは、任意プリミティブ、オブゞェクト、クラスなどにするこずができたす。
    • この簡単な意味を読みたしょう
    • 「穎あけ」を防ぐために䜿甚できたす
    • 開発ツヌルのプロバむダヌコンポヌネントずコンシュヌマヌコンポヌネントの珟圚の倀を衚瀺したすが、この倀ぞの倉曎の履歎は衚瀺したせん
    • 倀が倉曎されたずきに消費コンポヌネントを曎新したすが、曎新をスキップするこずはできたせん
    • 副䜜甚を凊理するためのメカニズムを提䟛したせん-レンダリングのみを担圓したす


  • React + Redux
    • 単玔な倀通垞はオブゞェクトを栌玍および管理したす
    • Reactコンポヌネントの倖郚だけでなく、任意のUIで動䜜したす
    • この簡単な意味を読みたしょう
    • 「穎あけ」を防ぐために䜿甚できたす
    • 操䜜を初期化し、レデュヌサヌを実行するこずで倀を曎新できたす
    • 開発者ツヌルは、操䜜の初期化ず状態倉曎の履歎を衚瀺したす
    • ミドルりェアを䜿甚しお副䜜甚を凊理する機胜を提䟛したす
    • コンポヌネントがストアの曎新をサブスクラむブし、ストア状態の特定の郚分を取埗し、コンポヌネントの再レンダリングを制埡できるようにしたす




明らかに、これらは異なる機胜を備えた完党に異なるツヌルです。それらの間の唯䞀の亀点は、「穎あけ」を防ぐこずです。



コンテキストずuseReducer



「ContextvsRedux」の議論の問題の1぀は、人々が実際に「useReducerを䜿甚しお状態ずコンテキストを管理し、倀を枡す」ずいう意味であるこずが倚いこずです。しかし、代わりに、圌らは「私はコンテキストを䜿甚しおいたす」ず蚀うだけです。私の意芋では、これが、文脈が「囜家を支配しおいる」ずいう神話の維持に寄䞎する混乱の䞻な理由です。



Context + useReducerの組み合わせを怜蚎しおください。はい、この組み合わせはRedux + React-Reduxず非垞によく䌌おいたす。これらの組み合わせは䞡方ずも次のずおりです。



  • プリペむド
  • レデュヌサヌ機胜
  • 操䜜を初期化する機胜
  • 倀を枡し、ネストされたコンポヌネントで読み取る機胜


ただし、それらの間にはただいく぀かの重芁な違いがあり、それらの機胜ず動䜜に衚れおいたす。私は、これらの違いを指摘しおきた 、リアクトReduxのを、ずコンテキスト行動ず リアクトでのレンダリングにほが完党ガむド。芁玄するず、次の点に泚意しおください。



  • Context + useReducerは、珟圚の倀をコンテキストに枡すこずに䟝存しおいたす。React-Reduxは珟圚のReduxストアむンスタンスをコンテキストに枡したす
  • ぀たり、useReducerが新しい倀を生成するず、䞀郚のデヌタのみを䜿甚しおいる堎合でも、コンテキストにサブスクラむブされおいるすべおのコンポヌネントが匷制的に再描画されたす。これにより、状態倀のサむズ、眲名されたコンポヌネントの数、および再レンダリングの頻床によっおは、パフォヌマンスの問題が発生する可胜性がありたす。React-Reduxを䜿甚するず、コンポヌネントはストア倀の特定の郚分をサブスクラむブし、その郚分が倉曎された堎合にのみ再描画できたす


他にも重芁な違いがありたす。



  • Context + useReducerはReactの組み蟌み機胜であり、それ以倖では䜿甚できたせん。ReduxストアはUIに䟝存しないため、Reactずは別に䜿甚できたす
  • React DevTools , . Redux DevTools , ( , type and payload),
  • useReducer() middleware. useEffect() useReducer(), useReducer() middleware, Redux middleware


ここでは䜕である セバスチャンMarkbageはコアチヌムのアヌキテクトず反応コンテキストを䜿甚しおに぀いお語った



「私の個人的な意芋は、新たなコンテキストが䟋えばロヌカラむズやテヌマなど可胜性は䜎い䜎呚波の曎新のために䜿甚する準備ができおいるずいうこずです。たた、叀いコンテキストが䜿甚されたすべおの堎合に䜿甚できたす。静的な倀の堎合、サブスクリプションによる曎新のその埌の配垃。 Fluxのような州のディストリビュヌタヌの代わりずしお䜿甚する準備はできおいたせん。」



状態のさたざたな郚分に耇数の個別のコンテキストを蚭定し、䞍芁な再レンダリングを回避し、スコヌプの問題を解決するこずを掚奚するWeb䞊の蚘事はたくさんありたす。䞀郚の投皿では、独自の「コンテキストコンポヌネント」を远加するこずも提案され おいたす。これには、React.memo、useMemoの組み合わせが必芁であり、アプリケヌションの各郚分でコヌドを2぀のコンテキストに適切 に分割する必芁がありたす1぀はデヌタ甚、もう1぀は曎新機胜。もちろん、この方法でコヌドを曞くこずもできたすが、この堎合、React-Reduxを再発明しおいたす。



したがっお、Context + useReducerは最初の抂算でRedux + React-Reduxの軜量な代替手段ですが、これらの組み合わせは同䞀ではありたせんが、context + useReducerはReduxを完党に眮き換えるこずはできたせん



適切なツヌルの遞択



適切なツヌルを遞択するには、ツヌルが解決するタスクず、盎面するタスクを理解するこずが非垞に重芁です。



ナヌスケヌスの抂芁



  • 環境

    • 「ドリル」なしでネストされたコンポヌネントにデヌタを転送する


  • useReducer

    • レデュヌサヌ機胜を䜿甚しお耇雑なコンポヌネントの状態を制埡する


  • コンテキスト+ useReducer

    • レデュヌサヌ関数を䜿甚しお耇雑なコンポヌネントの状態を管理し、「ドリル」せずにネストされたコンポヌネントに状態を転送したす


  • 戻っおきた

    • レデュヌサヌ機胜で非垞に耇雑な状態を制埡する
    • 状態が時間ずずもに倉化した時期、理由、方法のトレヌサビリティ
    • 状態管理ロゞックをUIレむダヌから完党に分離したい
    • 異なるUIレむダヌ間で状態管理ロゞックを配垃する
    • ミドルりェアの機胜を䜿甚しお、操䜜を初期化するずきに远加のロゞックを実装する
    • 状態の特定の郚分を保存する機胜
    • 再珟可胜な゚ラヌレポヌトを取埗する機胜
    • 開発䞭にロゞックずUIをすばやくデバッグする機胜


  • Redux + React-Redux

    • Reduxのすべおのナヌスケヌス+ ReactコンポヌネントがReduxストアず察話する機胜




もう䞀床名前付きツヌルはさたざたな問題を解決したす



掚奚事項



では、䜕を䜿甚するかをどのように決定したすか



これを行うには、アプリケヌションの問題を最もよく解決するツヌルを決定する必芁がありたす。



  • 「ドリル」を避けたいだけの堎合は、コンテキストを䜿甚しおください
  • , , + useReducer()
  • , , .., Redux + React-Redux


アプリケヌションに状態を管理するための2〜3のコンテキストがある堎合は、Reduxに切り替える必芁があるず思いたす。



「Reduxを䜿甚するには倚くの定型コヌドを曞く必芁がある」ずよく耳にしたすが、「最新のRedux」を䜿甚するず、習埗ず䜿甚がはるかに簡単になりたす。公匏の ReduxToolkitはテンプレヌトの問題を解決し、React-Reduxフック はReactコンポヌネントでReduxを簡単に䜿甚できるようにしたす。



もちろん、䟝存関係ずしおRTKずReact-Reduxを远加するず、組み蟌みのコンテキスト+ useReducerよりもアプリケヌションバンドルが増加したす。しかし、このアプロヌチの利点は、欠点をカバヌしおいたす-より良い状態トレヌス、より単玔でより予枬可胜なロゞック、改善されたコンポヌネントレンダリングの最適化。



䞀方が他方を陀倖しないこずに泚意するこずも重芁です-Redux、Context、およびuseReducerを䞀緒に䜿甚できたす。「グロヌバル」状態をReduxに、ロヌカル状態をコンポヌネントに保存するこずをお勧め したす。アプリケヌションのどの郚分をReduxに保存し、どの郚分をコンポヌネントに保存するかを決定するずきは泚意が必芁 です。..。したがっお、Reduxを䜿甚しおグロヌバル状態を保存し、Context + useReducerを䜿甚しおロヌカル状態を保存し、Contextを䜿甚しお静的な倀をすべお同じアプリケヌションに同時に保存できたす。



繰り返しになりたすが、すべおのアプリケヌションの状態をReduxに保存する必芁がある、たたはReduxが垞に最良の゜リュヌションであるず䞻匵しおいるわけではありたせん。私のポむントは、Reduxは良い遞択であり、Reduxを䜿甚する理由はたくさんあり、䜿甚料は倚くの人が考えるほど高くはないずいうこずです。



最埌に、contextずReduxは他に類を芋ないものではありたせん。状態管理の他の偎面に察凊する他の倚くのツヌルがありたす。MobXは、OOPずオブザヌバブルを䜿甚しお䟝存関係を自動的に曎新する䞀般的な゜リュヌションです。州の曎新に察する他のアプロヌチには、Jotai、Recoil、およびZustandが含たれたす。React Query、SWR、Apollo、Urqlなどのデヌタラむブラリは、サヌバヌキャッシュ状態を操䜜するための䞀般的なパタヌンを簡単に䜿甚できるようにする抜象化を提䟛したす同様のラむブラリRTKク゚リがRedux Toolkitにたもなく 登堎したす。



この蚘事が、コンテキストずReduxの違い、およびどのツヌルをい぀䜿甚すべきかを理解するのに圹立぀こずを願っおいたす。枅聎ありがずうございたした。



All Articles