useItemsを作る

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

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

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行になる

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 から呼んでください。

ヒント

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

できているか

  • くつの一覧が2件出ている
  • トップスの一覧が出ている
  • トップスに T シャツが並んでいる