Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
unstated-next による Redux に頼らない状態管理の考察
Search
Yoshihide Jimbo
July 19, 2019
Programming
9
5.1k
unstated-next による Redux に頼らない状態管理の考察
React.kyoto v0.3.0 でのLT発表資料です。
https://react-kyoto.connpass.com/event/137847/
Yoshihide Jimbo
July 19, 2019
Tweet
Share
More Decks by Yoshihide Jimbo
See All by Yoshihide Jimbo
高齢者でも使えるプロダクトUIの挑戦 / Designing User Interfaces for the Elderly
jmblog
32
27k
雰囲気でやってる人向けの Redux 再入門
jmblog
21
6.3k
わかりやすいグラフを作ろう
jmblog
3
1.3k
Web Components で 社内 UI ライブラリを作っている話
jmblog
11
4.1k
gulp: The Good Parts
jmblog
29
5.8k
CSS in JS と CSS Modules
jmblog
25
4.6k
PostCSS とは何か
jmblog
38
9.6k
Kaizen Platform における UI ライブラリのワークフロー
jmblog
30
6k
フロントエンドエンジニアのための Dotfiles
jmblog
53
8.4k
Other Decks in Programming
See All in Programming
Symfony Mapper Component
soyuka
2
730
あれやってみてー駆動から成長を加速させる / areyattemite-driven
nashiusagi
1
200
Zoneless Testing
rainerhahnekamp
0
120
Fibonacci Function Gallery - Part 1
philipschwarz
PRO
0
210
Итераторы в Go 1.23: зачем они нужны, как использовать, и насколько они быстрые?
lamodatech
0
740
テストコード文化を0から作り、変化し続けた組織
kazatohiei
2
1.5k
命名をリントする
chiroruxx
1
400
コンテナをたくさん詰め込んだシステムとランタイムの変化
makihiro
1
130
From Translations to Multi Dimension Entities
alexanderschranz
2
130
Cloudflare MCP ServerでClaude Desktop からWeb APIを構築
kutakutat
1
540
PSR-15 はあなたのための ものではない? - phpcon2024
myamagishi
0
110
フロントエンドのディレクトリ構成どうしてる? Feature-Sliced Design 導入体験談
osakatechlab
8
4.1k
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
45
7k
Reflections from 52 weeks, 52 projects
jeffersonlam
347
20k
Practical Orchestrator
shlominoach
186
10k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
GitHub's CSS Performance
jonrohan
1030
460k
The Cult of Friendly URLs
andyhume
78
6.1k
Designing for Performance
lara
604
68k
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.3k
Embracing the Ebb and Flow
colly
84
4.5k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
45
2.2k
Visualization
eitanlees
146
15k
Transcript
unstated-next による Redux に頼らない状態管理の考察 React.kyoto v0.3.0 | Jul 19, 2019
神保 嘉秀 @jmblog じんぼ よしひで
None
今⽇話すこと • unstated-next の紹介 • 気になる点や個⼈的な所感
unstated-next の紹介
https://github.com/jamiebuilds/unstated-next unstated-next
Hooks の登場によって、 Redux などの「状態管理ライブラリ」に頼らず、 React の Context と Hooks だけで状態管理を実装することが
可能になった。 unstated-next はその実装をサポートしてくれる、 必要最⼩限なライブラリ(わずか 200バイト)
unstated-next と unstated の関係 • unstated というライブラリもあってちょっとややこしい。 • 開発者はどちらも @jamiebuilds
⽒。 • unstated は Context を活⽤したシンプルな状態管理ライブラリ。 2018年前半に発表された。 • その後、React から Hooks がリリースされ、unstated のコンセプトをよりコン パクトに実現できるようになったため、Hooks ベースの API に⼀新して unstated-next という別パッケージで 2019年5⽉にリリースされた。
まず、 Context と Hooks だけで状態管理を実装すると こんなコードになる
useState() あるいは useReducer() を使い、 state とその更新 ロジックを内部に保持したカスタム Hook を⽤意する。
このカスタムHook をコンポーネントで直接利⽤すると、Hook 内の state は コンポーネントごとのローカル state となるが、Context で管理することで、 同じ
state の値を複数のコンポーネントで利⽤できるようになる。
<Context.Provider> にカスタムHookの中⾝を渡す。 これにより、Contextの中⾝ = state が更新されると、 コンポーネントが変更を検知して、再描画するようになる。
コンポーネントでは useContext() を使って、 Context の中⾝ = state を取得し利⽤することができる。
これだけで⼗分機能する。
state logics こういうイメージ Context custom hook
Context を Container(容器、⼊れ物)と呼ぶと、 よりイメージしやすくなる。 Container state logics custom hook
さっきのコードを unstated-next を使って 書き換えてみると、こうなる。
createContainer(customHook) で Container を作成し、 カスタムHookを格納する。
Container は Context と同様、Provider を持つ。
コンポーネントでは useContainer() を使って、 Container の中⾝ = state を取得し利⽤することができる。
これだけ。
unstated-next を使わなくても⼗分シンプルだが、 unstated-next による「Container」という概念を使うことで よりわかりやすくなる。
Redux よりも優れている点 • ファイルサイズは 1/40 • 学習コストが圧倒的に低い(Context と Hooks さえ知っていればいい)
• ほぼ素の React なので、どんなライブラリとも連携しやすい • パフォーマンスの⾯でも有利
Redux よりも優れている点 • ファイルサイズは 1/40 • 学習コストが圧倒的に低い(Context と Hooks さえ知っていればいい)
• ほぼ素の React なので、どんなライブラリとも連携しやすい • パフォーマンスの⾯でも有利 ← どういうことか?
Redux Store container component container component container component container component
Redux では、State が更新されると、マウント中の すべての Container Component(Store とつながっているコンポーネント)が、変更の通知を受けとって、 mapStateToProps(ある いは useSelector) を実⾏する mapStateToProps() mapStateToProps() mapStateToProps() mapStateToProps()
Redux Store container component container component container component container component
処理の遅い mapState が1つ存在していると、state が変更されるたびに毎回実⾏されるため、 アプリケーション全体のパフォーマンスを落とす重⼤なボトルネックとなる。 mapStateToProps() mapStateToProps() mapStateToProps() mapStateToProps()
Redux Store container component container component container component container component
「⽬に⾒えて遅くはないが、微妙に遅い」という mapState でも、たくさん存在すると、 やはりパフォーマンス劣化の要因となってくる。 mapStateToProps() mapStateToProps() mapStateToProps() mapStateToProps()
reselect によるメモ化など、 回避するためのベストプラクティスは存在するが、 そもそも、グローバルな単⼀の Store に すべてのコンポーネントが依存している という構造が引き起こす問題。
component component component component component container container container container 次のように、Container
(≒ Store) を複数に分けて、コンポーネントが本当に必要としている 場合だけ共有するようになっていれば、この問題は避けられる。
component component component component component container container container container もしパフォーマンス上問題のあるコンポーネントが存在していても、⾃分に関係のない
state が 変更されたときは何も起こらないので、コンポーネントが与える影響範囲は限定される。
unstated-next では、 Redux のようにアプリケーション全体の State を ⼀つの巨⼤な Container で管理するのではなく、 適切な粒度に分割して管理することが推奨されている。
ただし、Container の粒度に関する制約やルールは 存在していないので、⾃分でルールを決めて運⽤する必要がある。
気になる点や個⼈的な所感
Container の最適な粒度は? • ⼩さすぎると管理が煩雑になりそうだし、⼤きすぎると Redux が抱える のと同じ問題を引き起こす危険性が増す。 • まずは、ある程度の機能ごとに分割してみて、少しづつ調整していく感じ になりそう。
Container の最適な粒度は? • 正規化(normalize)されたデータは判断しやすい。 例えば、製品データ を「byId」と「visibleIds」に正規化したとすると、 それぞれを Container にすれば、<ProductList> と
<ProductDetail> で必 要とする State が良い感じに分離できる。
Redux で Store を複数に分割すればいいのでは? • Redux の FAQ に回答が載っている。 可能は可能だけど、Redux
DevTools とか使えなくなるし、単⼀の Store で使ってもらうことを想定している、とのこと。 https://redux.js.org/faq/store-setup#can-or-should-i-create-multiple- stores-can-i-import-my-store-directly-and-use-it-in-components- myself
「Provider ⼊れ⼦地獄」にならないか? • 多くの Container を必要するコンポーネントでは <Container.Provider> の⼊れ⼦がかなり深くなる。
「Provider ⼊れ⼦地獄」にならないか? • helper 関数を⽤意するぐらいしか回避策はなさそう。 https://github.com/jamiebuilds/unstated-next/issues/ 35#issuecomment-500255562 • ⼊れ⼦があまりにも深い場合は、Container の粒度が細かすぎるか、コン
ポーネントの責務が⼤きすぎる可能性が考えられるので、 リファクタリングのポイントといえるかも。
最適化のコツは? • Redux での「reselectを使いましょう」的な、unstated-next ならではの 最適化テクニックは特にない。 • 素の React とほぼ同じなので、React
のスタンダードな最適化がそのまま 使える。 https://github.com/jamiebuilds/unstated-next#tip-3-optimizing- components
デバッグはどうする? • 専⽤のデバッグツールはない。 • React Developer Tools に Hooks のサポートが⼊っていて、最新の
state の値は確認できるが、変更履歴などは確認できない。 https://github.com/facebook/react-devtools/pull/1272 • これが⼀番つらいところかも。
今すぐ Redux を捨てて unstated-next に乗り換えるべきか? • Redux よりも簡単にコーディングできるのは間違いないが、Redux とは 別の全体設計⼒が試される。
• 既存のアプリケーションに導⼊するのであれば、パフォーマンスチューニ ングの⼀環として、書き換えが頻発する State の⼀部を unstated-next に 置き換えてみるのはありだと思う。
スケールするのか?(⼤規模アプリでも使えるか?) • Redux を使って安定した⼤規模アプリケーションを実装できる⼒量があれ ば、unstated-next を使ってもうまくいくのではないか。 • 個⼈的には、最適なアプリケーションのアーキテクチャを探っていきた い。
スケールするのか?(⼤規模アプリでも使えるか?) • Container はクリーンアーキテクチャの Presenter(ユースケースやエンティティのデータ 形式を変換して、外界である UI に伝える役割)に あたるように思うが、React にがっつり依存して
いるのでこのレイヤーなのか少しモヤモヤする。 • クリーンアーキテクチャに適⽤するなら unstated-next ではなく unstated のほうが ぴったりはまりそうな印象。
もし実戦投⼊してノウハウが溜まったら、ぜひシェアしてください!
おわり