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で作ったフォームをApollo_Clientで投げたらいい感じだった件.pdf
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
asazu taiga
March 21, 2023
Technology
1k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Jotaiで作ったフォームをApollo_Clientで投げたらいい感じだった件.pdf
asazu taiga
March 21, 2023
More Decks by asazu taiga
See All by asazu taiga
副業やってみた
asazutaiga
0
400
Hydrationから知るAstro, Qwik
asazutaiga
0
770
(LT)ApolloClientとGraphQL Code Generatorの話
asazutaiga
0
140
2021新春Reactが怖くなくなる話
asazutaiga
0
260
Other Decks in Technology
See All in Technology
Slack上でインフラをトラブルシュートする! Agentic Platform Engineeringの第一歩
teru0x1
5
1.8k
2026-09-18 gotanda.sre Terraformで複数環境作ったり、複数Stateに分割したりそれとTerragrunt / Terraform multi envs and multi states
masasuzu
3
620
JSONataとAWS Step Functionsで目指すRuntimelessな世界
mu7889yoon
0
290
え、こんなに早く改修できるの?──新人エンジニアとスクラムマスターの2人が語る、AI×アジャイル開発の現場
ysasago
2
530
銀行勘定系システムにおける開発プロセス刷新×AIによる環境モダナイゼーション / Development Process Transformation and AI-Driven Environment Modernization
muit
1
2.4k
開発投資の期待値を上げるプロダクトロードマップづくり ~プロダクトエンジニアが越境して事業を伸ばす~
kekekenta
1
220
今話題のAI「Jev」って何? 宇宙最速で学ぶ会
minorun365
PRO
30
17k
「ピッケル本」日本語版は4.0(第6版)が出版されるべき / pickaxe4-nagoyark05
kakutani
2
220
積み重なった技術負債への挑戦 〜初手としての全社ゴト化〜
techtekt
PRO
0
1.4k
aws-iot-platform-architecture-use-cases.pdf
ma2shita
0
390
Vibe Coding で作ったプロダクトをどう安全に動かすか / How to Safely Run Products Built with Vibe Coding
glidenote
0
320
AIによるクリエイティブ生成を行う上での試行錯誤
plaidtech
PRO
0
160
Featured
See All Featured
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
520
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
700
Producing Creativity
orderedlist
PRO
348
41k
Are puppies a ranking factor?
jonoalderson
2
3.9k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6.2k
Heart Work Chapter 1 - Part 1
lfama
PRO
10
36k
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
300
SEO for Brand Visibility & Recognition
aleyda
0
4.7k
Claude Code のすすめ
schroneko
67
230k
Become a Pro
speakerdeck
PRO
31
6.3k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Typedesign – Prime Four
hannesfritz
42
3.2k
Transcript
Jotaiで作ったフォームを Apollo Clientで投げたら いい感じだった件 Asazu Taiga @JADE K.K. 2023.3.21 Saitama.js@大宮 【React】
Saitama.js オフライン開催 おめでとうございます! あーしもよろこんでいます ※公式の利用ルールに則り、非営利目的にて春日部つむぎさん素材を利用させていただいております
タイトルに「いい感じ」とありますが、 本当にいい感じなのか?は 皆さんの目でお確かめください (登壇申し込み時点ではいい感じだと思ってた)
自己紹介 • Asazu Taiga • twitter ◦ @AsazuTaiga • 所属
◦ 株式会社JADE • 最近好きなもの ◦ VTuberの音楽 ◦ ボイロキッチン動画 ▪ (自炊しないのに)
Agenda
Agenda • Jotaiの紹介 • Apollo Clientの紹介 • GraphQL Code Generatorの紹介
• Jotaiを使ったフォームの作成 • デモ • ちょっといい感じポイント • ちょっとどうかなポイント • まとめ • 質疑応答
Jotaiの紹介
Jotaiとは? • グローバルな状態管理ライブラリ • Recoilに触発されたアトミックなアプローチ • アトムの組み合わせによる依存関係に基づく自動最適化 ◦ 再レンダリング問題の解決、メモ化が不要 •
シンプルなuseStateの置き換えから複雑な アプリケーションまで幅広く対応 ◦ ユーティリティも豊富にある
Jotai サンプル(公式から引用) import { atom, useAtom } from 'jotai' //
Create your atoms and derivatives const textAtom = atom('hello') const uppercaseAtom = atom( (get) => get(textAtom).toUpperCase() ) // Use them anywhere in your app const Input = () => { const [text, setText] = useAtom(textAtom) const handleChange = (e) => setText(e.target.value) return ( <input value={text} onChange={handleChange} /> ) }
Jotai サンプル(公式から引用) const Uppercase = () => { const [uppercase]
= useAtom(uppercaseAtom) return ( <div>Uppercase: {uppercase}</div> ) } // Now you have the components const App = () => { return ( <> <Input /> <Uppercase /> </> ) }
Apollo Clientの紹介
Apollo Clientとは? • JavaScript向けの包括的な状態管理ライブラリ ◦ GraphQLクライアント ◦ ローカルとリモートの両方のデータを管理 • データの取得、キャッシュ、変更を行い、
UIを自動的に更新 • GraphQL Code Generatorと組み合わせることで、 TypeScriptとの統合がより便利になる
Apollo Client サンプル(公式から引用) const GET_LOCATIONS = gql` query GetLocations {
locations { id name description photo } } `;
Apollo Client サンプル(公式から引用、一部略) function DisplayLocations() { const { loading, error,
data } = useQuery(GET_LOCATIONS); if (loading) return <p>Loading...</p>; if (error) return <p>Error : {error.message}</p>; return data.locations.map(({ id, name, description, photo }) => ( <div key={id}>(中略...)</div> )); }
GraphQL Code Generatorの紹介
GraphQL Code Generatorの雰囲気が伝わる図 .graphql ドキュメント .graphqls スキーマ @graphql-codegen/cli 各種プラグイン (TypeScriptの型定義生成、
Apolloのhooksのラッパー生成 etc…) generated.ts
Jotaiを使ったフォームの作成
None
None
None
Jotaiを使ったフォームの作成 ※jotai-formというatomWithValidate()を提供する utilライブラリもありますが、今回は使いません 理由 • Jotai本体だけで十分に柔軟な表現ができる(気がする) • validate()関数をアトムに追加できるだけなので 恩恵がさほど大きくない(気がする)
Jotaiを使ったフォームの作成 - nameフィールドの例 // エラーメッセージを表示するかどうかを判定するためのatom(フォーム全体で共有) const shouldShowErrorMessageAtom = atom(false); const
nameAtom = atom(""); const nameSchema = z .string() .min(3, "名前は3文字以上で入力してください") .max(20, "名前は20文字以内で入力してください");
Jotaiを使ったフォームの作成 - nameフィールドの例 const nameErrorAtom = atom((get) => { const
name = get(nameAtom); const result = nameSchema.safeParse(name); if (result.success) { return ""; } return result.error.issues[0].message; }); const nameDisplayErrorAtom = atom((get) => { const shouldShow = get(shouldShowErrorMessageAtom); const error = get(nameErrorAtom); return shouldShow ? error : ""; }); export const useName = () => { const [value, setValue] = useAtom(nameAtom); const errorMessage = useAtomValue(nameDisplayErrorAtom); return { value, setValue, errorMessage }; };
デモ
デモ Website https://asazutaiga.github.io/jotai-examples/dist/index. html Repository https://github.com/asazutaiga/jotai-examples
ちょっといい感じポイント
ちょっといい感じポイント • クロスフィールドバリデーションが書きやすい • Mutation引数等、型変換をかませた派生atomが便利 • 利用側のコードがシンプルになる • 状態依存部分を最小限に切り出したコンポーネントを書 けば再レンダリングは控えめ
クロスフィールドバリデーションが書きやすい const passwordErrorAtom = atom((get) => { const password =
get(passwordAtom); // example: cross field validation // 実際こんなことはしないと思うが、例として const name = get(nameAtom); if (name === password) { return "名前とパスワードは異なるものにしてください "; } return ""; });
Mutation引数等、型変換をかませた派生atomが便利 // mutationの引数:GraphQL Code Generatorで生成した型を使うことができる // この例では単にそのまま値を各フィールドに渡しているだけだが、ここで適切な変換をかませることもできる const createUserVariablesAtom =
atom<CreateUserMutationVariables>((get) => ({ input: { name: get(nameAtom), email: get(emailAtom), password: get(passwordAtom), }, })); export const useCreateUserVariables = () => useAtomValue(createUserVariablesAtom);
Mutation引数等、型変換をかませた派生atomが便利 // 使う側はこんなにシンプル! // (いっそこれらをまとめたhookを作ってしまうのもよいが、ややオーバーか?) const variables = useCreateUserVariables(); const
[createUser, { loading }] = useCreateUserMutation({ variables, });
利用側のコードがシンプルになる const NameInput = () => { const { value,
setValue, errorMessage } = useName(); return ( <FormControl error={!!errorMessage}> <TextField label="Name" value={value} onChange={(e) => setValue(e.target.value)} /> <FormHelperText>{errorMessage}</FormHelperText> </FormControl> ); }; const InputView = () => { return ( <Stack gap={2} component="form" onSubmit={(e) => e.preventDefault()}> <NameInput /> <EmailInput /> <PasswordInput /> <Stack direction="row" gap={2}> <ResetButton /> <NextButton /> </Stack> </Stack> ); };
状態依存部分を最小限に切り出したコンポーネントを 書けば再レンダリングは控えめ デモで見てもらったように、 フォーム全体の再レンダリングはリセット時や モード(入力or確認)の切り替え時にしかおきません
ちょっとどうかなポイント
ちょっとどうかなポイント • テンプレ的な記述を多く書くのが大変 • フィールドが増えた際に依存フィールドの修正もれそう • グローバルで命名の衝突を避けようとすると変数名が長 くなりがち
テンプレ的な記述を多く書くのが大変 すでに見てもらったように、一つのフィールドに対して • 値atom • 内部エラーatom • 表示用エラーatom の3つは最低でも定義したくなる フィールドが増えれば、それだけatomの管理も大変に...
フィールドが増えた際に依存フィールドの修正もれそう // フォームの入力値をリセットするためのatom const resetFormAtom = atom(null, (get, set) =>
{ set(nameAtom, ""); set(emailAtom, ""); set(passwordAtom, ""); set(shouldShowErrorMessageAtom, false); }); addressが増えたら ここに足す...
フィールドが増えた際に依存フィールドの修正もれそう // フォーム全体をまたいで、エラーがあるかかないかを判定するためのatom const hasErrorAtom = atom((get) => { const
nameError = get(nameErrorAtom); const emailError = get(emailErrorAtom); const passwordError = get(passwordErrorAtom); return nameError || emailError || passwordError; }); ここもやんけ...
グローバルで命名の衝突を避けようとするとatom名が長 くなりがち • フォームの種別+フィールド名(+小区分)+atom ◦ createUserNameAtom ◦ createUserNameErrorAtom ◦ createUserNameDisplayErrorAtom
まとめ
まとめ • 派生状態を作りやすいJotai(atomベースの状態管理)の 特徴が、フォームの状態管理と結構マッチしている? • Apolloのことを散々書きましたが、APIのInputの型が あればGraphQLでもRESTでも関係ないですね(今更) • フォームの状態管理はみんな苦しんでいると思うので、 ひとつのありうる選択肢として捉えるとよさそう
Special Thanks 春日部つむぎさん(かわいい) Chat GPT(スライド作成手伝ってくれた)
質疑応答