はじめに
React customHooks を利用してロジックとUIを切り離すまでをやってみたシリーズ
今回は、Create処理をcustomHooksとして切り出すための実装について書きます。
これまで
Hasuraにユーザーのデータと仮定してデータを作成し
データを外部APIとして取得できるようにして、Next.js(apollo)を使って、クエリやミューテーションできるようにしました
Hasuraから取得したユーザーデータの一覧ページと詳細ページを作りながら、SG
とISR
を学んできました
このシリーズの目次
- このシリーズの方針
- customHooks を利用してロジックとUIを切り離すまで
最終的なゴール
以下のような構成のアプリを作ることです。
目的(最終的なゴールを達成する)
- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上
customHooks作成に必要なファイルを作成
components/
hooks/
└── useCreateForm.ts
pages/
customHooks作成
モジュールのimport
import { useState, ChangeEvent, FormEvent } from 'react'
import { useMutation } from '@apollo/client' // apolloを用いた通信処理
import { CREATE_USER } from '../queries/queries' // クエリコマンド
import { CreateUserMutation } from '../types/generated/graphql' // クエリコマンドに対応したデータ型
カスタムフックの定義
export const useCreateForm = () => {}
2つのuseStateの定義
export const useCreateForm = () => {
const [text, setText] = useState('')
const [username, setUsername] = useState('')
}
create処理を実装
前作ったやつをそのまま持ってきただけ
export const useCreateForm = () => {
const [text, setText] = useState('')
const [username, setUsername] = useState('')
const [insert_users_one] = useMutation<CreateUserMutation>(CREATE_USER, {
update(cache, { data: { insert_users_one } }) {
const cacheId = cache.identify(insert_users_one)
cache.modify({
fields: {
users(existingUsers, { toReference }) {
return [toReference(cacheId), ...existingUsers]
},
},
})
},
})
}
これでユーザーの新規作成処理が実装できました。
input要素を入力したときのイベント処理の実装
export const useCreateForm = () => {
const [text, setText] = useState('')
const [username, setUsername] = useState('')
const [insert_users_one] = useMutation<CreateUserMutation>(CREATE_USER, {
update(cache, { data: { insert_users_one } }) {
const cacheId = cache.identify(insert_users_one)
cache.modify({
fields: {
users(existingUsers, { toReference }) {
return [toReference(cacheId), ...existingUsers]
},
},
})
},
})
}
const handleTextChange = (e: ChangeEvent<HTMLInputElement>) => {
setText(e.target.value)
}
引数はイベント要素を受け取るようにして、setText()
だけする処理にしています。
ユーザー名を変える処理の実装
export const useCreateForm = () => {
const [text, setText] = useState('')
const [username, setUsername] = useState('')
const [insert_users_one] = useMutation<CreateUserMutation>(CREATE_USER, {
update(cache, { data: { insert_users_one } }) {
const cacheId = cache.identify(insert_users_one)
cache.modify({
fields: {
users(existingUsers, { toReference }) {
return [toReference(cacheId), ...existingUsers]
},
},
})
},
})
}
const handleTextChange = (e: ChangeEvent<HTMLInputElement>) => {
setText(e.target.value)
}
const usernameChange = (e: ChangeEvent<HTMLInputElement>) => {
setUsername(e.target.value)
}
submitしたときの処理の実装
export const useCreateForm = () => {
const [text, setText] = useState('')
const [username, setUsername] = useState('')
const [insert_users_one] = useMutation<CreateUserMutation>(CREATE_USER, {
update(cache, { data: { insert_users_one } }) {
const cacheId = cache.identify(insert_users_one)
cache.modify({
fields: {
users(existingUsers, { toReference }) {
return [toReference(cacheId), ...existingUsers]
},
},
})
},
})
}
const handleTextChange = (e: ChangeEvent<HTMLInputElement>) => {
setText(e.target.value)
}
const usernameChange = (e: ChangeEvent<HTMLInputElement>) => {
setUsername(e.target.value)
}
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
try {
await insert_users_one({
variables: {
name: username,
},
})
} catch (err) {
alert(err.message)
}
setUsername('')
}
関数handleSubmit
が実行されたら
非同期で、関数insert_users_one
が実行されてユーザー情報を{}
オブジェクトの中に入れて送っています。
非同期処理が成功・失敗にかかわらず終わったら、ユーザーネームを空文字をsetStateしています(初期化)。
最終的な実装結果
クリックすると実際のコードが見れます
import { useState, ChangeEvent, FormEvent } from 'react'
import { useMutation } from '@apollo/client'
import { CREATE_USER } from '../queries/queries'
import { CreateUserMutation } from '../types/generated/graphql'
export const useCreateForm = () => {
const [text, setText] = useState('')
const [username, setUsername] = useState('')
const [insert_users_one] = useMutation<CreateUserMutation>(CREATE_USER, {
update(cache, { data: { insert_users_one } }) {
const cacheId = cache.identify(insert_users_one)
cache.modify({
fields: {
users(existingUsers, { toReference }) {
return [toReference(cacheId), ...existingUsers]
},
},
})
},
})
const handleTextChange = (e: ChangeEvent<HTMLInputElement>) => {
setText(e.target.value)
}
const usernameChange = (e: ChangeEvent<HTMLInputElement>) => {
setUsername(e.target.value)
}
const printMsg = () => {
console.log('Hello')
}
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
try {
await insert_users_one({
variables: {
name: username,
},
})
} catch (err) {
alert(err.message)
}
setUsername('')
}
return {
text,
handleSubmit,
username,
usernameChange,
printMsg,
handleTextChange,
}
}
最終的に作った関数をreturnしたり、検証用の関数なども入れてます。
まとめ
今回は、Create処理をcustomHooksとして切り出すための実装について書きました。
次回
customHooksを利用してロジックとUIを切り離すまでのうち、ロジック作成はできたので、UI部分となるコンポーネント作成をしていきます。
アウトプット100本ノック実施中