localStorageに保存すれば、データベースはいらない? よく出る6つの疑問
ブラウザの localStorage(ローカルストレージ)は、1行で値を保存できて、ページを再読み込みしても消えません。最初のアプリ作りで「これでデータの保存はできた」と感じやすい仕組みです。
ただ、使い始めのころに誤解しやすいポイントがいくつかあります。この記事では、よく出る疑問を6つのQ&Aで整理します。
コード例の実行結果は、ブラウザ(Safari と同じ WebKit エンジン)と Node.js v24.14.1 で実際に試して確認しました。
Q1. localStorage に入れたデータは、ほかの人にも見える?
別の端末やブラウザを使うほかの人からは見えません。localStorage は「そのブラウザの中」にだけ保存されます。
- 同じ人でも、別のパソコンやスマホでは見えない
- 同じパソコンでも、Chrome で保存したものは Safari では見えない
- ページのURLの「http/https」「ドメイン」「ポート番号」の組み合わせごとに分かれている
最後の点は、開発中にハマりやすいところです。たとえば localhost:3000 と localhost:3001 は別の保存場所です。Next.js の開発サーバーは、3000番が使用中だと3001番で起動するので、そのときは保存したはずのデータが空に見えます。
Q2. じゃあ、データベースの代わりになる?
用途しだいです。「自分だけが、このブラウザで使う」小さなアプリなら十分です。
逆に、次のどれかに当てはまるならデータベース(Supabase など)の出番です。
- ほかの人と同じデータを見たい(掲示板、共有の予定表など)
- 別の端末からも同じデータを見たい
- 消えたら困る(localStorage は、ブラウザの閲覧データやサイトデータを消すと一緒に消えます)
Q3. 配列やオブジェクトも、そのまま保存できる?
できません。localStorage が保存できるのは文字列だけです。そのまま入れると、文字列に変換された結果が保存されます。
localStorage.setItem("list", ["牛乳", "卵"]);
localStorage.getItem("list"); // "牛乳,卵"
localStorage.setItem("todo", { title: "本", done: false });
localStorage.getItem("todo"); // "[object Object]"
オブジェクトのほうは中身が失われています。保存するときは JSON.stringify で文字列にして、読み出すときに JSON.parse で元に戻します。
localStorage.setItem("todos", JSON.stringify([{ title: "本", done: false }]));
const todos = JSON.parse(localStorage.getItem("todos") ?? "[]");
todos[0].done; // false(true/false の値として戻る)
まだ一度も保存していないキーを読むと null が返ります。そのまま使うと配列のつもりのコードが止まるので、?? "[]" で「なければ空の配列」として扱っています。
Q4. 数字や true/false も、入れたまま戻ってくる?
戻ってきません。これも文字列になります。気づきにくいので要注意です。
localStorage.setItem("count", 3);
const count = localStorage.getItem("count"); // "3"(文字列)
count + 1; // "31"
localStorage.setItem("isDone", false);
if (localStorage.getItem("isDone")) {
// 文字列の "false" は中身があるので、ここが実行される
}
数字なら Number() で変換する、true/false なら Q3 と同じく JSON.stringify / JSON.parse を通す、と決めておくと迷いません。
Q5. パスワードなどの大事な情報を入れても大丈夫?
入れないでください。localStorage の中身は、そのページで動く JavaScript なら読めます。もし悪いスクリプトが紛れ込むと、まとめて読み出されてしまいます。また、そのブラウザを使える人なら、開発者ツールを開くだけで中身をそのまま読めます(家族と共用のパソコンなど)。
パスワードは保存しません。ログインの仕組みは自分で作らず、使っているサービス(Supabase など)の認証機能を使います。ログイン状態の保存や更新はサービスの仕組み(ライブラリ)が自動で行うので、自分で localStorage に書く必要はありません。
Q6. Next.js で「localStorage is not defined」と出るのはなぜ?
Next.js は、ページの一部をサーバー側でも実行します。サーバー側の実行環境(Node.js)からは、利用者のブラウザに保存された localStorage は読めません。実際に Node.js v24.14.1 で localStorage を読むと、ReferenceError: localStorage is not defined になりました(バージョンによって文言が違っても、原因と直し方は同じです)。
"use client" を付けた部品でも、最初の画面を作るために一度サーバー側で実行されます。そのため、部品の本体や useState の初期値で localStorage を読むと、このエラーになります。ブラウザで表示されたあとにだけ動く useEffect の中で読み出します。
typeof window !== "undefined" で分けて済ませる書き方もありますが、サーバーとブラウザで最初の表示が食い違い、別のエラー(Hydration エラー=サーバーが作った画面とブラウザの画面が合わない、というエラー)の原因になりやすいので、useEffect で読むほうが安全です。
"use client";
import { useEffect, useState } from "react";
export default function Memo() {
const [memo, setMemo] = useState("");
useEffect(() => {
setMemo(localStorage.getItem("memo") ?? "");
}, []);
return <p>{memo}</p>;
}
AIに頼むときのひと言
AIに「データを保存できるようにして」とだけ頼むと、手軽な localStorage を使った版が出てくることがあります。それ自体は悪くありませんが、Q2 の「ほかの人と見たい/別の端末でも見たい/消えたら困る」に当てはまるなら、保存先が合っていません。
頼むときに「このデータは自分専用か、ほかの人やスマホからも使うものか」を一言添えると、保存先の選び方まで含めて提案してもらいやすくなります。保存先を選べるようになると、AIが出したコードが自分のアプリに合っているかを判断する目も育ちます。
面談なしで、今日から始められます
この講座は 未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を全24セッションで体系化した教材付きプランです。無料相談を挟まず、申し込んだその日から教材で学習を始められます。AIが学習パートナーになって何度でも質問でき、つまずいた所だけチャットで直接サポートします。
- 今日から始める(教材完全版+月5,500円・チャット質問し放題・いつでも解約OK)→ https://menta.work/plan/20251?ref=menta-knowledge
- いきなりは不安な方へ:無料の教材体験版もあります(最初の数セッション分)→ プラン詳細をご覧ください

