Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
複雑なフォームの jotai 設計 / Designing jotai(state) for ...
Search
izumin5210
April 23, 2025
Programming
4.8k
10
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
複雑なフォームの jotai 設計 / Designing jotai(state) for Complex Forms #layerx_frontend
https://layerx.connpass.com/event/348773/
izumin5210
April 23, 2025
More Decks by izumin5210
See All by izumin5210
コンパウンドプロダクト開発のためのローカルプロセスマネージャー再発明 #layerxgo
izumin5210
0
700
in-process GraphQL のすすめ #ginzajs
izumin5210
4
1.5k
開発体験を左右するライブラリの API 設計 - GraphQL スキーマ構築ライブラリから考える #tskaigi
izumin5210
2
2.2k
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
2
1.1k
AI Agent の開発と運用を支える Durable Execution #AgentsInProd
izumin5210
8
3.1k
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
2.4k
Building AI Agents with TypeScript #TSKaigiHokuriku
izumin5210
6
1.8k
Web エンジニアが JavaScript で AI Agent を作る / JSConf JP 2025 sponsor session
izumin5210
4
3.6k
AI Coding Meetup #3 - 導入セッション / ai-coding-meetup-3
izumin5210
0
3.8k
Other Decks in Programming
See All in Programming
JRuby: Past, Present, and Future
headius
0
210
個人開発基盤をまるごとCloudflareに引っ越して爆速で総合的体験を向上させた話
tinykitten
0
210
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
550
JAWS-UG 東京支部が始める、JAWS-UG支部コラボ / JAWS-UG lunchtime LT Collaboration
y0hgi
0
160
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
320
すこし踏み込む CancellationToken
htkym
2
1.3k
一人だけ、Kiroが静止する日
hideg
0
130
Webの地図
yosuke_furukawa
PRO
6
4.9k
SONY CISC-NEWS NWS-1750 + NWB-225 フレームバッファの NetBSD/news68k ドライバ実装 / OSC2026Hiroshima
tsutsui
0
150
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
270
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
220
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
290
Featured
See All Featured
How to make the Groovebox
asonas
2
2.5k
Writing Fast Ruby
sferik
630
63k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
42k
Site-Speed That Sticks
csswizardry
13
1.5k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.5k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
The Limits of Empathy - UXLibs8
cassininazir
1
690
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
290
Build your cross-platform service in a week with App Engine
jlugia
234
19k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
250
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
3
3.8k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.9k
Transcript
複雑なフォームの jotai 設計 2025-04-23 Exploring State - LayerX Web Frontend
Night @izumin5210
@izumin5210 © LayerX Inc. whoami LayerX バクラク事業部 (2022-09 -) Platform
Engineering 部 Enabling チーム Staff Software Engineer Backend と Web Frontend などを書く Wantedly, Inc. (2018-04 - 2022-08) ISUCON14 4位 「状態管理ライブラリまだいらなくね?」 って言いがち
これまでのあらすじ © LayerX Inc. https://speakerdeck.com/izumin5210/number-newt-techtalk-vol-15 3
これまでのあらすじ © LayerX Inc. https://speakerdeck.com/izumin5210/number-newt-techtalk-vol-15?slide=24 4
これまでのあらすじ © LayerX Inc. https://speakerdeck.com/izumin5210/number-newt-techtalk-vol-15?slide=28 5
jotai/状態の設計について、具体例とともに深ぼっていきます © LayerX Inc. 6
例. 外貨対応の金額入力 React Hook Form + Zod の実装例 © LayerX
Inc. 通貨指定して金額入力できる 日本円換算の金額で設定された 上限バリデーションがある 7
jotai 設計: なるべく状態ではなく値に jotai での実装例 © LayerX Inc. 例. 外貨対応の金額入力
amountJpy は状態(State)ではなく、 他の値・状態から決まる値(Derived Value) 状態(State)は減らしたい 状態は書き込み可能 変な値が書き込まないような書き込みロジックが必要 考えないといけないことが増える! 8
jotai 設計: バリデーション対象は直接の 入力値に限らない © LayerX Inc. 例. 外貨対応の金額入力 ユーザが直接入力した値でなくとも、
ユーザ入力から間接的に決まるものであれば 対象になりうる React Hook Form + Zod だと watch + setValue で つらいことになりがち jotai ならキレイに書ける 9
jotai 設計: バリデーション対象は直接の入力値に限らない © LayerX Inc. 例. 外貨対応の金額入力 バリデーション対象であるということは、ドメイン上に概念・名前がある(たぶん) ドメイン上に概念・名前があるなら、コード上でも同じ概念・名前をつけよう
バリデーションに埋まったドメインロジックを自然に分離できるのもポジティブ 10
現実はもっと複雑 © LayerX Inc. 11
例. 外貨対応の金額入力 Lv.2 こうなってくるとテストも大変… React Hook Form での実装例(ちょっと悪意がある) © LayerX
Inc. 通貨指定して金額入力できる 日本円換算の金額で設定された 上限バリデーションがある 換算レートは外部から取得する ← New! 12
jotai 設計: Derived Atom は 非同期もそのまま扱える jotai での実装例 © LayerX
Inc. 例. 外貨対応の金額入力 Lv.2 Derived Atom は Promise を返すことができる derive() を使った async sometimes パターン で Promise<T> | T が返る React につなぐときは必要に応じて Suspend してくれる 非同期の値を書き込むための状態は不要 非同期であっても書き味は大きく変わらない 「データグラフでドメインを自然に表現できる」 という利点 が損なわれない Jotai v2を使いこなすために実は必須級な“async sometimes”パターンの解説 https://zenn.dev/uhyo/articles/jotai-v2-async-sometimes 13
現実はまだまだ複雑 © LayerX Inc. 14
例. 外貨対応の金額入力 Lv.3 © LayerX Inc. 通貨指定して金額入力できる 日本円換算の金額で設定された 上限バリデーションがある 換算レートは外部から取得する
ただし、ユーザが自分で入力することも可能 ← New! e.g. 日本円を現地通貨に両替したときの領収書からレートを決める場合 15
jotai 設計: async sometimes atom から 更に derived atom を作れる
© LayerX Inc. 例. 外貨対応の金額入力 Lv.3 [async fetchedRate, manualRate] → async rate → async amountJpy atom() が derived() に変わるが、 データの依存グラフを作って必要な値を得る… というモデルは変わらない 16
現実は… © LayerX Inc. 17
例. 外貨対応の金額入力 Lv.4 © LayerX Inc. 通貨指定して金額入力できる 日本円換算の金額で設定された 上限バリデーションがある 換算レートは外部から取得する
ただし、ユーザが自分で入力することも可能 カード決済の場合、金額とレートはカードの決済情報から決まる ← New! 18
jotai設計: ユーザが直接編集する状態 と、別の値から決まる値は分ける © LayerX Inc. 例. 外貨対応の金額入力 Lv.4 特に「変更不可能な補完入力」については、
ユーザが入力する状態と分けてあげる 「状態」の責務を減らす 「その値がどこから来たのか」を コード上・動作上いずれにおいてもトレース可能にする 19
現実… © LayerX Inc. 20
現実… まあ今日は一旦これくらいで © LayerX Inc. 21
ここまでのまとめ 現実っぽい例をもとに、jotai の設計プラクティスをいくつか紹介した © LayerX Inc. なるべく状態ではなく値に バリデーション対象は直接の入力値に限らない バリデーションのために設計を歪めない ユーザが直接編集する状態と、別の値から決まる値は分ける
状態の責務を減らし、その値の由来をトレースしやすくしておく Derived Atom は非同期もそのまま扱える async sometimes atom から更に derived atom を作れる 同期・非同期が混ざっていても、コード上は(比較的)滑らかに記述できる 22
ここまでのまとめ… からの学び 結局なにが言いたいか © LayerX Inc. なるべく状態(State)ではなく値(Derived Value)に 状態(State)を減らす ユーザが直接編集する状態と、別の値から決まる値は分ける
状態(State)の責務を減らす Derived Atom は非同期もそのまま扱える 非同期処理からの書き込みを回避でき、結果として状態(State)が減る 23
「状態」はむずかしい! © LayerX Inc. 「状態」を「読み書き可能な値」ととらえると、「書き込み」の制御が必要になる 「書き込む」という処理を適切に呼び出させないといけない 「状態」の利用者側に「考える」 「適切に使う」という仕事を押し付けている (この 利用者
は AI であることも多くなる… どうやって徹底させるか) なので、「状態」は減らしたい なるべく Derived Value にする jotai であれば、非同期処理が混ざっても、わりと自然に Derived Value として記述できる なくせない「状態」であっても、責務を減らすことで利用者の負担を減らせる 今回の例だと「ユーザが直接編集する状態と、別の値から決まる値は分ける」ことで 状態ごとのユースケースを絞り、利用者の考えることを減らす 24
我々は「状態」を減らすために jotai を使っているのかもしれない… © LayerX Inc. 25