「Harajuku.ts Meetup 〜 Recoilの事例集めました〜」参加メモ
ナレッジワークのよしこさんが登壇するというのを会社のtimesで知ったため、イベント内容をメモしながら聴きました。
よしこさんの発表が終わった直後に電話がかかってきてしまったため、okunoさんとna2hiroさんの発表はメモが少なめになっています。
イベントページ
私はYouTubeライブで参加しました。
以下メモです。
イベント趣旨のご説明
Recoilはリリースして2年半経っているが、事例があまり出てこない
Twitterでつぶやいたところ、登壇者が集まってくれた
どのように使っている/いないかの発表をしてくれる
ハッシュタグ #harajuku_ts
登壇
「ステート管理を超えるRecoil運用の考え方」@uhyo_
事前アンケート結果の共有
Jotaiもかなり似たライブラリなので、脳内変換しながらお聞きください
差異に個人的に興味があります
自己紹介
22年10月からバベル勤務
ブルーベリー本の著者
話すこと
aileadフロントエンドにReactとともにRecoilを使用。なぜ、どうやったのか
2つ
実はFlixって天才だったのでは
Recoilくんとならやり直せる気がする
実はFlixって天才だったのでは
ReactはUI構築以外の仕事をさせない方がいいのでは
UI以外のことの例、外部からのデータの読み込みとか
理想的なアーキテクチャ、Reactにはレンダリングしてもらって、外部からのデータ読み込みとかは外にやってもらったほうがいいのでは?と思った
この図、Fluxと似ている
FluxだとStoreとなっているところが、コア層と整形層に分離した
単純なFluxだと成果物が「でかい状態の塊」になるのが辛い
Recoilの運用アイデア
コア層と整形層をやってもらう
Recoilくんとならやり直せる気がする
Recoilのいいところ
atomとselectorがあり、コアな状態がどれなのかを設計上明らかにしやすい
非同期ネイティブであり、非常期処理もselectorとして扱える
思想がReact本体と近い「ロジック用のReact」のような使い心地
atomとselectorの使い分けがだいじ
他に従属しない状態がatom
それ以外は何が何でもselector
Recoil層とReact層の境界は当然フック
具体例の説明
ReactにUI以外のことを無理にやらせると、アプリケーションの整合性を保つのが困難になる
検索条件が変わったのに検索結果が前のままという中途半端な状態がレンダリングされてしまう
Recoil内部で整合線の取れた状態を計算し、終わってからReactに
ReactとRecoilの整合性保証、似ている部分がある
React:状態→画面の整合性
Recoil:グラフ→状態の整合性
整合性の棲み分け
Recoilを活用するデータフロー設計
シンプル・ローレベルなAPIから構成されている
望ましい設計を保ちやすい
具体例
まとめ
Recoilをロジックに用いる設計を試している
改めて見てみると、Fluxの良いところを受け継ぎ良くないところを直したような構成になっている
ReactはそろそろUIライブラリに専念させてあげたい
文章で読みたいかたはこちら
ナレッジワークでのState管理とRecoil活用事例@yoshiko_pg
(公開されたらスライドを貼る。)
自己紹介
よしこ
株式会社ナレッジワークのフロントエンドエンジニア
GUIをSPAとして作るのが好き
自社での技術スタックや設計をZennで公開しています
下記のStateについての記事をじっくり深ぼる
話すこと
前提:SPAにおける3種類のState
ナレッジワークでどうStateを管理しているのか
Recoilを使ったGlobal State運用ルール
Recoilをどう運用しているか
Recoilを使ったGlobal Stateの変更フロー
前提:SPAにおける3種類のState
Stateは結構フロントエンド開発において難しいことの一つ
変化しうるデータが「状態」としてある色々な「状態」がある。
全部の状態をSingle Stateに入れていた感じの設計もあったかもしれない
分解してみると、こういう状態がある
「Componentを超えて共有する必要のある状態:Global State」と「特定の状態に閉じた状態:Local State」
Componentを超えて共有する必要のある状態:Global State
Componentは、Root Componentは例外として、それ以外の任意のComponentを指している
「超えて」は、自分を超えて、他のComponentだったり、自分自身へもunmountされてライフサイクル超えたときとか
閉じた状態ならuseStateとかすればいいが、そこを超える必要が出てくると、もっと永続した状態が長いところ、Root Componentにも出せる
ここで言っているGlobal Stateは、言い換えるとRoot ComponentのLocal Stateとも言えるかもしれない
URLやLocal Storageなどの永続する値は含んでいません
特定の状態に閉じた状態:Local State
もう一段階ブレイクダウンした
「Componentを超えて共有する必要のある状態:Global State」をブレイクダウン
Global Stateに置かなければいけないデータって何だろう
大体はサーバーデータのキャッシュでは?
従来のGlobal Stateからサーバーデータのキャッシュを除くと、残るデータはわずか
であればそれらは必要最低限の仕組みでそれぞれに管理すればよいのでは?
ということで、こう
状態
Componentを超えて共有する必要のある状態
サーバーデータのキャッシュ:①Server Data cache
それ以外:②Global State
Componentに閉じた状態:③Local State
上記の②Global StateでRecoilを使っている
Recoilを使ったGlobal State運用ルール
前提
今回紹介するナレッジワークでのRecoilの使い方は、ピュアなGlobal Stateとしてのかなりシンプルな使い方になる。
APIも9割方atomしか使っていない。
前段でStateを3つに分類したことでGlobal Stateの担う役割が最小限になり、最大限シンプルな使い方でもニーズを十分カバーできるようになった。
Recoilを使ったGlobal State運用ルール
①置き場所・命名のルール
src/globalStates以下に1Stateあたり1ファイルを作成する
RecoilはStateたくさん作れる。使いたい状態ごとに1ファイル作っている
ファイル名はxxxState.ts
ファイル名単体で見た時も役割が明確
ファイル名をRecoilのKeyにする
Recoilは、ファイル名が衝突するとエラーになる
ファイル名をそのままkeyにすることで、Global Stateの中に同じ名前のファイルを入れることができないため、keyが衝突しないことを担保できる。頑張らなくても済む仕組み。
②露出させるインターフェイスのルール
StateそのものやsetStateなどRecoilのAPIを直接露出させず、React用/Write用のカスタムフックひとつずつのみ露出させる
ライブラリの知識を隠蔽できる。腐敗防止層にもなる
サーバーからしたら何のライブラリで管理しているのかは知らなくても良い情報
今後Global State管理ライブラリを乗り換えたくなったときも、このGlobal StateレイヤーのファイルとRoot ComponentのProviderだけ書き換えればOKになる
ライブラリを隠蔽するのはナレッジワーク内で他にも使っている箇所がある。一層噛ませて吸収できるようにしておくのはおすすめ
(主にWriteで)操作に「意味」を持たせる
useStateを提供してしまうと、操作の意味や文脈が使う側に委ねられてしまう
「このStateはこういう操作ができる」をState側に提供させ、使い方を限定させる
Read hookのルール
StateのRead hookはuse 〇〇Stateの命名規則でexport
大体useRecoilValueをラップしているだけ
toastStateをサンプルにしている
任意のComponent/Usecaseから利用可能
Write hookのルール
State のWrite hookはuse〇〇Mutatosとしてexportする
setStateをラップしたWrite関数のまとまりを返す。setStateは直接露出させない。行いたい操作ごとに専用の関数を提供することで、このStateはどんな操作を想定しているのか?も伝えることができる
Write関数を必ずメモ化する(使う側でdepsに入れることを想定)
任意のUsecaseから利用可能
Callback hookのルール
ほとんどないが、ちょっとだけある
知りたい人はuhyoさんのブログ読もう
Recoilを使ったGlobal Stateの変更フロー
これで伝わるかな
ユーザーがクリック
Componentがクリックをハンドリング
Usecaseというレイヤーを設けており、そのUsecaseをComponentが呼び出す
Global Stateの書き込みは、Usecaseのレイヤーからだけ許可することにしてデータフローの方向性を保っているので、Usecaseから書き込みをする
Global Stateの値が変わったら、それをSubscribeしているComponentが自動で再レンダリングされる
Usecaseの記事、去年の大晦日に公開したので是非読んで
おやくそく
We’re Hiring!!!
『それでもどうしてRecoilを使うのか』@okunokentaro
Recoilが出番となるとき
Propsバケツリレーがあまりにも頻繁で生産性・可読性ともに低下を実感するとき
React Contextの出番になりそうな全ページ全コンポーネントで共有する情報があるとき
積極的Recoilも消極的Recoilもアリ
(電話に出ていたため、メモが少ない)
Recoilと将棋ったー@na2hiro
(電話に出ていたため、メモを取っていない)
感想
かなり断片的な感想だが、Recoilを使ったGlobal State運用ルールの「Recoilはファイル名が衝突するとエラーになるため、ファイル名をそのままRecoilのKeyにすることで、keyが衝突しないことを担保できる」という部分、「人が頑張ってしっかりすること」に依存せずに「うっかりを仕組みで防いでいく」に寄せていく感じいいなと思った
フロントエンドエンジニアではないため難しいと感じる部分もあったが、それも含めていい刺激になってよかった。YouTube LIVEなので、もし配信が残るならokunoさんとna2hiroさんの発表も観てみよう