コース一覧
React Routerとアプリ設計
見た目と機能の分離

React Routerとアプリ設計

React Router、Routes・Route・Link、URLパラメータ、検索条件、404、見た目と機能の分離、合成、機能別フォルダを扱う全18レッスンのアプリ設計コースです。fleamaを商品一覧・詳細・出品・カート・マイページを持つ複数ページSPAとして完成させます。

1
ルーティング(React Router v7)
01. ルーティング導入15分
02. RoutesとRoute15分
03. 遷移を作る15分
04. URLパラメータ15分
05. 検索条件をURLに15分
06. 404ページ15分
07. つくる - ページ分割完了20分
08. 第7章クイズ15分
2
コンポーネント設計パターン
01. 見た目と機能の分離15分
02. 合成で組み立てる15分
03. 機能別フォルダ10分
04. つくる - 設計リファクタ20分
05. 第8章クイズ15分
3
総合制作
01. 購入フロー20分
02. マイページ20分
03. 仕上げ15分
04. 自由拡張20分
05. 完成と次のステップ10分

見た目と機能の分離

取ってくる係と並べる係

1つの部品が2つの仕事を持っている

いまの ItemList は、次の2つを1つの関数の中でやっています。

  • データを取ってくる仕事 (fetch と state と読み込み中の管理)
  • それを画面に並べる仕事 (JSX とクラス名)

動いてはいますが、困りごとが2つあります。まず、見た目だけを直したいときにも通信のコードを読むことになります。そして、同じ並べ方を「お気に入り一覧」でも使いたくなったとき、取得先が違うだけなのに JSX ごと複製することになります。

表示担当とデータ担当に分ける

そこで役割で2つに割ります。呼び方は次のとおりです。

  • 表示担当 (Presentational) — props で受け取ったものを並べるだけ。state も通信も持たない
  • データ担当 (Container) — 取ってきて、状態を持って、表示担当に渡すだけ。JSX はほぼ書かない

TypeScript (JSX)

type ItemListViewProps = { items: Item[]; }; export function ItemListView({ items }: ItemListViewProps) { return ( <div className="list"> {items.map((item) => ( <div className="card" key={item.id}> <p className="title">{item.title}</p> <p className="price">{item.price} 円</p> </div> ))} </div> ); }

表示担当は props だけを見ます。これが守れていると、渡す配列を変えるだけでどんな画面も再現できます。

データ担当は渡すだけにする

TypeScript (JSX)

export function ItemList() { const [items, setItems] = useState<Item[]>([]); useEffect(() => { fetch("/api/items") .then((res) => res.json()) .then((data: Item[]) => setItems(data)); }, []); return <ItemListView items={items} />; }

分かれ目は覚えやすい形になっています。表示担当に useState と fetch が出てきたら、分け方を間違えています。

演習

いまの ItemList を、表示担当の ItemListView とデータ担当の ItemList に分けます。

ヒント

ItemListView の props の型は { items: Item[] } の形です

Item の型は types.ts にあります。import type { Item } from "./types"; で読めます

ItemList の return は ItemListView を1つ返すだけになります

App.tsx
ItemList.tsx
ItemListView.tsx
mock-api.json
types.ts
プレビュー

できているか

  • カードが3枚並んでいる
  • 3枚とも価格が出ている
  • 帆布トートが出ている
  • 価格に 円 が付いている
  • 表示担当が items を並べている
  • 表示担当に state が残っていない
  • 表示担当に通信が残っていない
  • データ担当が表示担当に渡している
  • データ担当が見た目を持っていない
エディタを読み込んでいます