取ったデータを描画する
このレッスンで分かること
- 取ってきた配列から一覧を組み立て、画面に出せる
- 待っている間に「読み込み中」を出し、届いたら消せる
- 描画を関数に切り出しておくと、データの出どころを変えても書き直さずに済むと分かる
- 件数のような集計を、取ってきたデータから作れる
取ったデータを描画する とは
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.count | 5 という数値 |
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.json は count も一緒に返してくれますが、絞り込みを入れたあとは 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);課題
- fetch より先に #status へ「読み込み中」を入れる
- 1 件につき article.work-card を作り、h3 に title、p.work-meta に年と表示回数を入れる
- 描き直す前に .work-list を空にする
- #works-count に、描いた件数を入れる