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
Jotaiで作ったフォームをApollo_Clientで投げたらいい感じだった件.pdf
Search
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
380
Hydrationから知るAstro, Qwik
asazutaiga
0
760
(LT)ApolloClientとGraphQL Code Generatorの話
asazutaiga
0
120
2021新春Reactが怖くなくなる話
asazutaiga
0
250
Other Decks in Technology
See All in Technology
Claude Code×Terraform IaC テンプレート駆動開発
itouhi
1
450
LLMと共に進化するプロセスを目指して
ymatsuwitter
12
3.7k
"何を作るか"を任される エンジニアは、どう育つのか
yutaokafuji
1
270
Dynamic Workersについて
yusukebe
2
640
トークン数だけでは測れない — Claude Code 組織展開の効果検証から学んだこと
makikub
0
140
MCP Appsを作ってみよう
iwamot
PRO
4
230
AI駆動開発が変える、大規模開発の前提 ーHuman in the Loop から Human on the Loop へ / AIE2026
visional_engineering_and_design
30
22k
Socrates × Looker 〜セマンティックレイヤーで進化するデータ分析エージェント〜
hanon52_
2
1.5k
やさしいA2A入門
minorun365
PRO
7
770
美味しいスイスチーズを作ろう🧀🐭
taigamikami
1
270
「気づいたら仕事が終わっている」バクラクAIエージェント本番運用の裏側 / layerx-bakuraku-aie2026
yuya4
19
11k
スキルと MCP ツール、責務をどう分けるか? AI が迷わないインターフェース設計の戦略
cdataj
0
200
Featured
See All Featured
エンジニアに許された特別な時間の終わり
watany
107
250k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
200
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
570
The Limits of Empathy - UXLibs8
cassininazir
1
350
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
610
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
The agentic SEO stack - context over prompts
schlessera
0
800
Agile that works and the tools we love
rasmusluckow
331
21k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
820
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
220
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
360
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(スライド作成手伝ってくれた)
質疑応答