6日目のゴールと今日やること
6日目のテーマは
「ミニ総合アプリを“保存できて、集計もできる、小さくても本格的なアプリ”にする」
ことです。
ここまでであなたは、
入力(タイトル+カテゴリ+完了フラグ)
一覧表示
削除
条件分岐(表示モード:すべて/未完了/完了)
を組み合わせて、かなり実用的な ToDo 風アプリを作ってきました。
6日目はここに、
入力したデータをブラウザに保存する(localStorage)
アプリ起動時に保存データを読み込む
件数の集計(合計・未完了・完了)を表示する
条件分岐で「集計表示」を切り替える
という、“アプリとしての完成度”を一段上げる要素を足していきます。
データを「ブラウザに保存する」イメージをつかむ
なぜ保存が必要なのか
今のままだと、ページをリロードすると
配列 items の中身は消えてしまいます。
せっかく入力したデータが消えるのは、
アプリとしてはかなりつらいですよね。
そこで使うのが
ブラウザに用意されている「localStorage」という仕組みです。
これは簡単に言うと、
文字列を「キーと値」で保存しておける小さな倉庫
だと思ってください。
重要なポイント:保存できるのは「文字列だけ」
localStorage はオブジェクトや配列をそのまま保存できません。
ですが、JSON という形式の文字列に変換すれば保存できます。
オブジェクトや配列
→ JSON.stringify で文字列にする
→ localStorage に保存
→ 取り出すときに JSON.parse で元に戻す
この流れを覚えれば、
「アプリの状態を保存する」という世界に一気に近づきます。
items を localStorage に保存する仕組みを作る
保存用のキーを決める
まずは「どの名前で保存するか」を決めます。
const STORAGE_KEY = "miniAppItems";
JavaScriptこのキーは、
「このアプリ専用の引き出しのラベル」
のようなものです。
保存する関数を作る
function saveItems() {
const json = JSON.stringify(items);
localStorage.setItem(STORAGE_KEY, json);
}
JavaScriptここでやっていることは、
items(配列)
→ JSON.stringify で文字列に変換
→ localStorage.setItem で保存
という流れです。
読み込む関数を作る
function loadItems() {
const json = localStorage.getItem(STORAGE_KEY);
if (!json) return;
try {
const data = JSON.parse(json);
if (Array.isArray(data)) {
items.length = 0;
data.forEach((item) => items.push(item));
}
} catch (e) {
console.error("保存データの読み込みに失敗しました", e);
}
}
JavaScriptここでの深掘りポイントは、
保存データがない場合もあるので null チェックをする
JSON.parse は失敗する可能性があるので try / catch で囲む
配列を丸ごと入れ替えるのではなく、中身だけ入れ替える
という「ちょっと大人な安全設計」です。
いつ保存して、いつ読み込むかを決める
読み込みのタイミング
ページを開いたとき(スクリプトが読み込まれたとき)に
一度だけ loadItems を呼びます。
loadItems();
renderList();
updateStatusMessage();
JavaScriptこれで、
「前回までの items の状態」が復元されます。
保存のタイミング
items が変わるタイミングで saveItems を呼びます。
例えば、次のような場所です。
新規追加後
更新後
完了フラグ切り替え後
削除後
イメージとしては、
「配列 items をいじったら、最後に saveItems()」
という癖をつける感じです。
例:
function addItem(title, category) {
const newItem = {
id: nextId,
title,
category,
done: false
};
items.push(newItem);
nextId += 1;
saveItems();
}
JavaScriptfunction toggleDone(id) {
const target = items.find((item) => item.id === id);
if (!target) return;
target.done = !target.done;
saveItems();
}
JavaScriptfunction deleteItem(id) {
const newItems = items.filter((item) => item.id !== id);
items.length = 0;
newItems.forEach((i) => items.push(i));
saveItems();
}
JavaScriptこのように、
「状態を変えたら保存する」というルールを徹底すると、
アプリの一貫性が保ちやすくなります。
集計機能を作って「アプリの全体像」を見える化する
どんな集計を出したいか
例えば、次のような情報があると便利です。
全件数
未完了の件数
完了の件数
これを画面の上か下に表示しておくと、
「今どれくらいタスクがあるのか」が一目でわかります。
集計関数を作る
function getStats() {
const total = items.length;
const doneCount = items.filter((item) => item.done).length;
const todoCount = total - doneCount;
return {
total,
doneCount,
todoCount
};
}
JavaScriptここでのポイントは、
filter を使って「done が true のものだけ」を数える
未完了は「全体 − 完了」で求める
というシンプルなロジックです。
集計結果を表示する
HTML に表示場所を用意します。
<div id="statsArea"></div>
JavaScript で更新関数を作ります。
const statsArea = document.getElementById("statsArea");
function renderStats() {
const stats = getStats();
statsArea.textContent =
`合計: ${stats.total} 件 / ` +
`未完了: ${stats.todoCount} 件 / ` +
`完了: ${stats.doneCount} 件`;
}
JavaScriptそして、
renderList と同じタイミングで呼び出します。
renderList();
renderStats();
updateStatusMessage();
JavaScriptまたは、
items を変更する関数の最後で呼んでも構いません。
条件分岐で「集計表示のメッセージ」を変える
状態に応じてメッセージを変える
例えば、次のようなルールを作れます。
タスクが 0 件 → 「まだ何も登録されていません」
未完了が 0 件 → 「すべて完了しました。お疲れさまです!」
それ以外 → 「未完了がまだあります」
これを statusArea に表示してみます。
function updateStatusMessage() {
const stats = getStats();
if (stats.total === 0) {
statusArea.textContent = "まだデータがありません。最初の1件を追加してみましょう。";
return;
}
if (stats.todoCount === 0) {
statusArea.textContent = "すべて完了しています。お疲れさまです!";
return;
}
statusArea.textContent = `未完了の項目が ${stats.todoCount} 件あります。`;
}
JavaScriptここでの深掘りポイントは、
「集計結果(数字)を条件分岐に使う」
というところです。
今までは
done フラグや viewMode を条件にしていましたが、
今日は「件数」という数値を条件に使っています。
6日目の全体イメージ(重要部分だけまとめ)
状態の一覧
items(配列:タイトル・カテゴリ・done を持つオブジェクトの集まり)
nextId(次に使う ID)
viewMode(表示モード:all / todo / done)
localStorage に保存されている JSON 文字列
これらを組み合わせて、
入力
一覧
削除
条件分岐(表示モード・完了状態・件数)
が動いています。
追加・削除・完了切り替えの流れ(要約)
入力 → バリデーション → items に push / 更新
→ saveItems() で保存
→ renderList() で一覧更新
→ renderStats() で集計更新
→ updateStatusMessage() で状態メッセージ更新
この一連の流れを意識できると、
「アプリ全体がどう動いているか」を
頭の中で追いやすくなります。
今日いちばん深く理解してほしいこと
6日目であなたが手に入れたのは、
配列やオブジェクトを「一時的なもの」ではなく
「保存して、次回も使えるアプリの状態」として扱う感覚
と、
数を数えて、条件分岐に使い、
メッセージや UI を変えるという
「集計 × 条件分岐」の考え方です。
入力
一覧
削除
条件分岐
というキーワードは、
もう単なる文法の話ではなく、
「アプリの設計そのもの」として
あなたの中に根付き始めています。
7日目は、
このミニ総合アプリ全体を振り返りながら、
「自分は何ができるようになったのか」を
言葉にしていく仕上げの日にしましょう。

