前回【Next.js】Githubのような勉強記録アプリ①:簡単なTimer実装に続き、今回はLocalStorageを使って勉強内容を保存する方法を解説します。
勉強記録アプリを作る中で、「記録したデータをどのように保存するか」で悩む方も多いのではないでしょうか。特に、同じ日付のデータが重複した場合の扱いは、初心者がつまずきやすいポイントです。
この記事では、Next.jsとTypeScriptを使って、LocalStorageに勉強記録を保存する基本的な方法と、データが重複した場合の考え方について分かりやすく解説します。一見シンプルな処理に見えますが、実際に実装してみると考えることが多く、基礎の理解の大切さを改めて感じました。
- LocalStorageの基本的な使い方(保存・取得・削除)
- 配列やオブジェクトを扱う際のJSON変換
それでは、実装を見ていきましょう。
LocalStorageの構成
まずは、簡単にLocalStorageの構成や使い方についてまとめてみました。
・データは約5MBまで保存可能
・ブラウザから削除しない限り、基本的に半永久的に保存される
・同じブラウザ内でのみデータが保持される(端末やブラウザが変わると引き継がれない)
LocalStorageは、サーバーを使わずにデータを保存できるため、簡単なアプリケーションの状態管理や、一時的なデータ保存に適しています。ただし、ブラウザごとにデータが管理されるため、ユーザーが端末を変更した場合などはデータが共有されない点には注意が必要です。
基本操作
①データの保存 (setItem)
キー(Key)とバリュー(Value)のペアで管理します。値は文字列で保存する必要があります.
// localStorage.setItem('key', 'value');
localStorage.setItem('studyTime', '120');②データ取得(getItem)
設定したキーを使って値を取得します。
const time = localStorage.getItem('studyTime');
console.log(time); // "120"③データ削除(removeItem / clear)
特定の値を消すことも、すべてをクリアすることも可能です。
localStorage.removeItem('studyTime'); // 特定値削除
localStorage.clear(); // すべてのデータを削除④ 配列・オブジェクトを保存する場合 (重要!)
LocalStorageは文字列しか保存できないため、配列やオブジェクトをそのまま保存することはできません。そのため、JSON.stringify と JSON.parse を使って変換する必要があります。
保存する場合:
配列やオブジェクトは JSON.stringify を使って文字列に変換してから保存します。
const data = [{ title: "React勉強", duration: 120 }];
localStorage.setItem("studyData", JSON.stringify(data));
取得する場合:
取得したデータは文字列のため、JSON.parse を使って元の配列に戻します。
const stored = localStorage.getItem("studyData"); // データがあるか確認
const data = stored ? JSON.parse(stored) : []; // あれば変換、なければ空配列
console.log(data);localStorage.getItem は、データが存在しない場合 null を返します。そのため、null のまま処理するとエラーになる可能性があるため、三項演算子で分岐しています。
- データがある場合 → JSON.parse で配列に変換
- データがない場合 → 空の配列を初期値として設定
このようにすることで、安全にデータを扱うことができます。
よくあるミス
・JSON.stringify を忘れて保存してしまう
・JSON.parse をしないまま使おうとしてエラーになる
・null のまま処理してしまう
特に初心者の方はこの部分でつまずきやすいため、注意が必要です。
実装例(勉強記録アプリケーション)
LocalStorageを使って、実際に勉強記録アプリにデータ保存機能を実装しました。本来であればデータベースを使用した方が安定した管理が可能ですが、今回はシンプルな実装を目的としているため、LocalStorageを利用しています。
処理の流れ
今回の実装は、以下の流れでデータを保存しています。
・今日の日付を取得(キーとして使用)
・既存データを取得
・同じ日付があれば配列に追加
・なければ新しく配列を作成
・LocalStorageに保存
データ構造
{
"2026-04-28": [studyRecord, studyRecord],
"2026-04-27": [studyRecord]
}
日付をキーとして、その日の記録を配列で管理しています。

実装コード
// 今日の日付を取得
const now = new Date();
const today = `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,"0")}-${String(now.getDate()).padStart(2,"0")}`;
// 既存データを取得
const stored = localStorage.getItem("studyData");
const data: StudyData = stored ? JSON.parse(stored) : {};
// 日付ごとに処理
if (data[today]) {
data[today].push(studyRecord); // 既にある場合は追加
} else {
data[today] = [studyRecord]; // なければ新しく作成
}
// LocalStorageに保存
localStorage.setItem("studyData", JSON.stringify(data));
ポイント
・日付をキーとして管理することで、データを整理しやすくなる
・配列を使うことで、1日に複数の記録を保存できる
・LocalStorageは文字列のみ保存できるため、JSON変換が必要
このように、シンプルな構造でも基本を押さえることで、実用的なデータ管理が可能になります。
終わりに
シンプルな実装ですが、「キーを何にするか」「どう整理するか」を考える過程で、データ設計の奥深さを感じました。ただ保存するだけでなく、後から取り出しやすい形を作ることが重要ですね。
次回は、今回保存したデータを使って、GitHubのコントリビューションのような「勉強記録の可視化(芝生)」の実装に挑戦します!

