コース一覧
React状態管理:カスタムフック・Context・Reducer
useFormを作る

React状態管理:カスタムフック・Context・Reducer

カスタムフック、フックのルール、Context、useContext、useReducer、Actionのunion型を扱う全21レッスンの状態管理コースです。fleamaの商品・フォーム・テーマ・ユーザー・カート状態を、再利用可能なロジックと予測可能な状態遷移へ整理します。

1
カスタムフック
01. なぜカスタムフックか10分
02. useItemsを作る15分
03. useFormを作る15分
04. フックのルール15分
05. フックに型を付ける15分
06. つくる - フック化完了20分
07. 第4章クイズ15分
2
useContext
01. バケツリレーの限界15分
02. Contextを作る15分
03. useContextで使う15分
04. テーマの全体共有15分
05. ユーザー情報の共有15分
06. つくる - Context整備20分
07. 第5章クイズ15分
3
useReducer
01. setStateの散らかり15分
02. useReducer15分
03. Actionのunion型15分
04. カートreducer15分
05. 使い分け10分
06. つくる - カート完成20分
07. 第6章クイズ15分

useFormを作る

useForm が返す2つ

入力欄の数だけ state が増える

出品フォームには商品名と価格があります。素直に書くと、こうなります。

TypeScript (JSX)

const [title, setTitle] = useState(""); const [price, setPrice] = useState("");

ここに説明文とカテゴリと画像 URL が足されると、state が5つ、ハンドラも5つです。しかも出品フォームと、あとで作るプロフィール編集フォームで、同じ形のコードがまた並びます。前のレッスンの重複と同じ話です。

値をまとめて1つの state にする

入力欄ごとに state を分けず、オブジェクト1つで持ちます。

TypeScript (JSX)

const [values, setValues] = useState({ title: "", price: "" });

書き換えるときは、入力欄の name を手がかりにします。

TypeScript (JSX)

function handleChange(e: ChangeEvent<HTMLInputElement>) { const { name, value } = e.target; setValues((prev) => ({ ...prev, [name]: value })); }

[name] は「変数 name の中身をキーにする」という書き方です。name="title" の欄なら title が、name="price" の欄なら price が書き換わります。ハンドラは1つで、入力欄が何個あっても足りるわけです。

...prev を忘れると、打った欄以外が消えます。前の値を広げてから上書きする、この順番が要ります。

useForm として切り出す

この形は、どのフォームでも同じです。だから useItems と同じようにフックへ出します。

TypeScript (JSX)

export function useForm(initial: FormValues) { const [values, setValues] = useState(initial); function handleChange(e: ChangeEvent<HTMLInputElement>) { ... } function reset() { setValues(initial); } return { values, handleChange, reset }; }

返すのは値だけではありません。handleChange のような関数も一緒に返します。カスタムフックが返すのは「値と、それを扱う道具の一式」です。送信のあとに空へ戻す reset も、フォームなら必ず要るのでここに入れておきます。

演習

出品フォームの入力管理を useForm へ移します。

ヒント

const { name, value } = e.target; で欄の名前と打たれた文字が取れます

setValues((prev) => ({ ...prev, [name]: value })) の形です。丸かっこで包まないとブロックだと思われます

App.tsx 側は value={values.title} と onChange={handleChange} になります

App.tsx
useForm.ts
プレビュー

できているか

  • 商品名を打つと preview に出る
  • 価格を打って出品するとリストに増える
  • useForm が values を書き換えている
  • App.tsx が useForm を呼んでいる
  • 入力欄ごとの state が App.tsx から消えている
エディタを読み込んでいます