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

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分

useItemsを作る

useItems が返す 3 つ

カスタムフックは、ただの関数

前のレッスンで、取得のコードが2か所に並びました。これを1か所にまとめます。使うのは新しい仕組みではありません。名前が use で始まり、中でフックを呼ぶ関数を作るだけです。

TypeScript (JSX)

export function useItems(category: string) { const [items, setItems] = useState<Item[]>([]); const [loading, setLoading] = useState(true); useEffect(() => { setLoading(true); fetch("/api/items?category=" + category) .then((res) => res.json()) .then((data: Item[]) => { setItems(data); setLoading(false); }); }, [category]); return { items, loading }; }

JSX を返さないので、これはコンポーネントではありません。返すのは画面ではなく state と、それを動かす仕組みです。

使う側は2行になる

TypeScript (JSX)

function ShoesList() { const { items, loading } = useItems("shoes"); if (loading) return <p className="loading">読み込み中</p>; return <ul>{items.map((item) => <li key={item.id}>{item.title}</li>)}</ul>; }

12 行あった取得の手続きが消えて、画面のコードだけが残りました。トップスの一覧も useItems("tops") と書くだけです。再試行を足したくなったら、直す場所は useItems ひとつです。

state は共有されない

よくある勘違いを先に潰しておきます。useItems を2つの部品から呼んでも、items が混ざることはありません。共有されるのはコードであって、state ではありません。 呼んだ部品ごとに別の useState が作られます。中で使っている useState は、あくまで呼び出し元のコンポーネントのものです。

名前は use で始める

use で始めるのは、ただの慣習ではありません。React の開発ツールやエディタの検査は、この名前でフックかどうかを見分けています。fetchItems のような名前にすると、中でフックを呼んでいるのに誰も気付けず、ルール違反を見逃します。

演習

useItems.ts に取得のロジックを移し、App.tsx から fetch を無くします。useItems.ts は器だけ用意してあるので、中身を書いて App.tsx から呼んでください。

ヒント

依存配列に category を入れると、カテゴリが変わったときに取り直せます

useItems は JSX を返しません。返すのは { items, loading } のオブジェクトです

App.tsx では import { useItems } from "./useItems"; と書いて呼び出します

App.tsx
mock-api.json
useItems.ts
プレビュー

できているか

  • くつの一覧が2件出ている
  • トップスの一覧が出ている
  • トップスに T シャツが並んでいる
  • 取得のコードが useItems.ts に移っている
  • App.tsx が useItems を呼んでいる
  • App.tsx に fetch が残っていない
エディタを読み込んでいます