👀
"Next.jsを書いていて本気でつまずいたポイントまとめ(初心者〜中級向け)"
Next.jsを書いていて本気でつまずいたポイント(コード付きでシンプル解説)
こんにちは、シュートです。普段は学生をしながらTypeScriptを用いて、個人開発やチーム開発をしています!
Next.js と React を使う中で、「文法は知ってるのに挙動がよく分からない」場面が何度もありました。
この記事では、自分が本当に詰まった箇所だけを、原因 → コード例 → 解決策 の流れでシンプルにまとめます。
1. useState の値が更新されない問題
まず誰もが通る道。
const [count, setCount] = useState(0);
const handleClick = () => {
console.log(count); // 0 のまま
setCount(count + 1);
console.log(count); // 0 のまま
};
React の state 更新は同期ではなく “次のレンダーで反映される” のがポイント。
✔️ 解決策:関数型アップデート
setCount(prev => prev + 1);
2. useEffect の依存配列で無限ループ
useEffect(() => {
fetchData();
}, [data]); // data を fetchData が更新 → 無限ループ
✔️ 原因
依存配列に「更新される値」を入れている。
✔️ 解決策
useEffect(() => {
fetchData();
}, []); // 初回だけ
3. props が更新されない / 反映されない
// 親
<Child value={count} />
// 子
useEffect(() => {
console.log(value); // 更新されないように見える
}, []);
✔️ 解決策
useEffect(() => {
console.log(value);
}, [value]);
4. Next.js の “Server / Client” ミス
// Server Component 内
localStorage.getItem("token"); // ❌ ReferenceError
✔️ 対策
"use client";
useEffect(() => {
const token = localStorage.getItem("token");
}, []);
5. fetch が“2回実行される”問題
useEffect(() => {
fetch("/api/data");
}, []);
✔️ 原因
StrictMode による二回実行。
✔️ 対策(1回だけにしたい場合)
const data = await fetch("https://example.com").then(res => res.json());
6. app router のルーティング混乱
// app/users/[id]/page.tsx
export default function UserPage({ params }: { params: { id: string } }) {
return <div>User: {params.id}</div>;
}
覚えるポイントは2つだけ:
- フォルダ名 = URL
- [] = 動的パラメータ
7. Next.js で意識すると楽になること
- state の“持ち主”は一箇所にまとめる
- state は “その場では更新されない”
- useEffect の依存配列が挙動のすべて
- Server / Client の境界を意識する
- フォルダ = ルーティング
おわりに
今後は以下の記事を執筆予定
- Gemini / GPT-5 / Claude に同じタスクを投げた比較記事
- 各AI API(Responses / Gemini / Claude API)の実装メモ
- Zod / Firestore / Stripe まわりのトラブル集
- “AIと一緒に開発するときの流れ” の話
学生エンジニアとしての実体験ベースで書いていくので、ゆるく読んでもらえたら。
Discussion