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
AI Testing Talks: Challenges of Applying AI in Software Testing: From Hype to Practical Use
exactpro
PRO
1
140
価格.comをAI駆動で全面刷新する ー 30年分の技術的負債を返し、次の30年の土台をつくる ー / AI Engineering Summit Tokyo 2026
tkyowa
51
57k
Claude Code の Sandbox 機能を Anthropic Sandbox Runtime(srt) で試そう!/lets-play-anthropic-sandbox-runtime
tomoki10
1
240
ChatworkとBPaaS 異なる特性で学んだAI機能開発の ベストプラクティス
kubell_hr
2
3.2k
非エンジニアがClaudeと挑んだ「1ヶ月間プロダクト30本ノック」
askokc
0
140
「コーディング」しない人のための Claude Code 入門 ChatGPT の次の一歩 — 業務に組み込む 育成・共有・自動化
rfdnxbro
2
1.2k
Socrates × Looker 〜セマンティックレイヤーで進化するデータ分析エージェント〜
hanon52_
2
1.5k
「エンジニア進化論」2028年の開発完全自動化、エンジニアはどう進化するか
cyberagentdevelopers
PRO
1
180
Building applications in the Gemini API family.
line_developers_tw
PRO
0
2.3k
Djangoユーザが知っ得なPostgreSQL機能 - 設計の選択肢を増やす / Djang-use-PostgreSQL
soudai
PRO
0
210
Agentic Web
dynamis
1
190
中期計画、2回作ってみた ~業務委託と正社員、両方の視点から~
demaecan
1
450
Featured
See All Featured
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.9k
Designing for Timeless Needs
cassininazir
1
250
Faster Mobile Websites
deanohume
310
31k
Discover your Explorer Soul
emna__ayadi
2
1.1k
Agile that works and the tools we love
rasmusluckow
331
21k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Amusing Abliteration
ianozsvald
1
200
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
200
How GitHub (no longer) Works
holman
316
150k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
190
The Spectacular Lies of Maps
axbom
PRO
1
790
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.9k
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(スライド作成手伝ってくれた)
質疑応答