React の context API があれば redux は不要なのか

React hooksの登場とともに useContextが現れた当時、reduxは必要なくなる?と疑問に思って軽く調べた記憶がある。 当時は、mediumの記事 にたどり着いて
hooksはreduxに取って代わるものではなく、必要であるのであれば変わらずredux導入しなさい、という結論だけそうなのかーと受け入れていたが、 理解が浅く具体どんな場合にreduxが適するのか、が分かっていなかった。
本日改めて記事を読み返してちょっと腹落ちしたのでメモしておく。

本題

useContextとreduxを比べるとき、解決したいこととしては以下だと思う。
- 複数のコンポーネントで同一のstateを利用したい
- だが、親コンポーネントからpropを何度も経由してstateを受け渡すのは辛い

https://zenn.dev/luvmini511/articles/61e8e54853bc13#1.-%E3%83%A1%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%AE%E5%BF%85%E8%A6%81%E6%80%A7

上記の記事の 「1.メインストレージの必要性」の話。

これに対するuseContextとreduxが提供する機能にはそもそも違いがある。

mediumの記事には以下のようにあり

And while some developers opt to use context to manage their entire application state, that’s not really what it’s designed for. According to the docs,

Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.

In other words, things that aren’t expected to updated frequently.

developers は contextをアプリケーション全体のstate管理に利用しようとするが、contextはそういった目的で作られた訳ではない。
"contextは、認証されているユーザー、テーマ、優先言語など、Reactコンポーネントのツリーの「グローバル」と見なすことができるデータを共有するように設計されています。"
言い換えると、contextは頻繁に更新されることが期待されていないものである。

ということだった。
つまり、頻繁に更新されるstateを複数コンポーネントで利用するなら、contextよりもreduxの方がより目的に適した手法である。
contextを利用しても実現できるが、以下のようなデメリットもある。
コンポーネントの再利用性が損なわれる
↑ contextのProvider配下のコンポーネントは、context経由でstateを受け取れることを前提に作られ、 contextのProvider配下以外には利用できなくなるため 。 reduxであれば、一元管理のstoreにはどこからでもアクセスできるため、再利用しやすい 。
・contextのProvider配下のコンポーネントの不要な再レンダリングを起こしやすい
↑ 基本的にはcontextで管理しているstateが更新されると、contextのProvider配下のコンポーネントは全て再レンダリングされるため(回避策はあるが)。
reduxであれば、connectされている(またはuseSelectorを利用している)コンポーネントのみが再レンダリングされる 。

また、reduxを使うメリットとしては、複数のコンポーネントでstateを利用できるだけではなく以下のようなものがあり、これもreduxを利用する大きな理由となる。
- middlewareを利用できる
- 開発者ツールやデバッグ機能が充実している

ただし、reduxは学習コストが高い上にコード記述量も増えるので、導入は慎重に行いたいというのが自分の考え。

まとめ

reduxを利用するモチベーションは以下
- 頻繁に更新されるstateを複数コンポーネントで共有したい
- stateの更新に際してmiddlewareを利用したい
- stateの更新に際してreduxの充実した開発者ツールやデバッグ機能を利用したい

これらが、redux導入によるデメリット (学習コスト、コード記述量の増加、バンドルサイズの増加、ライブラリ管理コストなど) に見合っていれば、導入を検討したい。