取ったデータを描画する

このレッスンで分かること

  • 取ってきた配列から一覧を組み立て、画面に出せる
  • 待っている間に「読み込み中」を出し、届いたら消せる
  • 描画を関数に切り出しておくと、データの出どころを変えても書き直さずに済むと分かる
  • 件数のような集計を、取ってきたデータから作れる

取ったデータを描画する とは

fetch で受け取った配列を、そのまま画面の一覧に変える回です。データが手元の配列か通信で届いたものかで、描画のコードは変わりません。

手で書いた配列と、取ってきた配列は同じもの

第8章までは、作品の一覧をファイルの中に書いていました。

const works = [ { id: 1, title: "プロフィールサイト", year: 2026, views: 120 }, { id: 2, title: "自己紹介カード", year: 2026, views: 80 } ];

これが通信で届くようになっても、変数に入ったあとは何も変わりません。 配列は配列です。ですから、描画の部分は前のまま使えます。変わるのは「どこから works を手に入れるか」だけです。

const response = await fetch("https://yumesaku.tech/course-api/works.json"); const data = await response.json(); const works = data.works; // ここから先は前と同じ

works.json は配列そのものではなく、{ count, works } というオブジェクトを返します。取ってきたものが即座に配列とは限らないので、前のレッスンで書いたとおり、一度中身を見て入れ物の形を確かめてから取り出してください。

書きかた中身
data{ count: 5, works: [...] } というオブジェクト
data.count5 という数値
data.works作品 5 件が入った配列
data.works[0].title"プロフィールサイト"

描画は関数に切り出す

一覧を組み立てる処理は、fetch とは別の関数にしておきます。こうしておくと、あとで絞り込みや並び替えを足すときに、同じ関数を呼び直すだけで済みます。

function renderWorks(works) { const list = document.querySelector(".work-list"); list.textContent = ""; works.forEach((work) => { const card = document.createElement("article"); card.className = "work-card"; const heading = document.createElement("h3"); heading.textContent = work.title; const meta = document.createElement("p"); meta.className = "work-meta"; meta.textContent = work.year + " 年 / " + work.views + " 回表示"; card.append(heading, meta); list.append(card); }); }

最初の list.textContent = "" を忘れると、呼ぶたびにカードが積み上がります。描き直す前に消す、をひとつの型として覚えてください。

renderWorks は「配列をもらってカードを並べる」ことしか知りません。通信のことも、絞り込みのことも知らないままにしておくのがこつです。知らないぶんだけ、あとから使い回せます。

待っている間に何を出すか

通信は遅れて届きます。何も出さないでいると、利用者からは「壊れている画面」に見えます。ここは第8章でスピナーを出したのと同じ考えかたで埋めます。

async function loadWorks() { const status = document.querySelector("#status"); status.textContent = "読み込み中"; const response = await fetch("https://yumesaku.tech/course-api/works.json?delay=800"); const data = await response.json(); renderWorks(data.works); status.textContent = data.count + " 件の作品を読み込みました"; } loadWorks();

?delay=800 は、このコースの練習用の口だけが持っている指定です。800 ミリ秒だけ遅れて返してくれるので、速い回線でも「待っている状態」を自分の目で確かめられます。

書く順番が大事です。先に「読み込み中」を出してから await する。逆にすると、待ち終わってから「読み込み中」が出て、すぐ消えることになります。

待ちの表示は、通信が終わったら必ず消してください。「読み込み中」が残ったままカードが並んでいる画面は、利用者を不安にさせます。

0 件のときに何を出すか

配列が空でも forEach は静かに何もしません。エラーは出ませんが、画面には何も残らない一覧が空いたままになります。利用者から見れば「壊れている」と「0 件だった」の区別が付きません。

function renderWorks(works) { const list = document.querySelector(".work-list"); list.textContent = ""; if (works.length === 0) { const empty = document.createElement("p"); empty.textContent = "表示できる作品がありません"; list.append(empty); return; } works.forEach((work) => list.append(createWorkCard(work))); }

早めに return して抜けるこの形は、第6章で書いた早期 return と同じ考えかたです。0 件の分岐を先に片づけてしまうと、その下は「1 件以上ある場合」だけを考えて書けます。

練習用の口には ?empty=1 を用意してあります。付けると作品が 0 件で返るので、この分岐を実際に通せます。

件数はデータから作る

「5 件」のような数字を手で書いてはいけません。データが変われば数字も変わるべきだからです。

// 直したい書きかた。データが増えても 5 のまま count.textContent = "5 件"; // 取ってきたものから数える count.textContent = data.works.length + " 件";

works.jsoncount も一緒に返してくれますが、絞り込みを入れたあとは count と画面の件数がずれます。画面に出す件数は、実際に描いた配列の length から作るほうが安全です。

よくある間違い

data をそのまま配列として回そうとする

// 直したい書きかた。data はオブジェクトなので forEach が無い const data = await response.json(); data.forEach((work) => { /* ... */ }); // data.forEach is not a function // 中の配列を取り出してから回す data.works.forEach((work) => { /* ... */ });

描き直す前に消し忘れる

// 直したい書きかた。2 回呼ぶとカードが 10 枚になる function renderWorks(works) { works.forEach((work) => list.append(createCard(work))); } // 毎回まっさらにしてから並べる function renderWorks(works) { list.textContent = ""; works.forEach((work) => list.append(createCard(work))); }

読み込み中を await のあとに書く

// 直したい書きかた。待ち終わってから出るので、一瞬しか見えない const response = await fetch(url); status.textContent = "読み込み中"; // 送る前に出す status.textContent = "読み込み中"; const response = await fetch(url);

課題

  1. fetch より先に #status へ「読み込み中」を入れる
  2. 1 件につき article.work-card を作り、h3 に title、p.work-meta に年と表示回数を入れる
  3. 描き直す前に .work-list を空にする
  4. #works-count に、描いた件数を入れる

ヒント

index.html
script.js
プレビュー

できているか

  • fetch を送る前に読み込み中を出す
  • 作品 5 件ぶんのカードが並ぶ
  • 1 枚目のカードに作品名が入る
  • 取ってきた作品をすべて描く
  • 件数をデータから作って出す