forked from semi-23e/nextjs-todo-tutorial
ドキュメント更新
This commit is contained in:
@@ -102,6 +102,35 @@ git init
|
||||
git status
|
||||
```
|
||||
|
||||
**💡 コマンドの詳細説明:**
|
||||
|
||||
**git initとは?**
|
||||
|
||||
- 現在のディレクトリをGitリポジトリにします
|
||||
- `.git`という隠しフォルダが作られ、そこに変更履歴が保存されます
|
||||
- 一度だけ実行すればOK
|
||||
|
||||
**git statusとは?**
|
||||
|
||||
```bash
|
||||
# 実行例
|
||||
$ git status
|
||||
On branch main
|
||||
|
||||
No commits yet # まだコミットがない
|
||||
|
||||
Untracked files: # Gitが追跡していないファイル
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
README.md
|
||||
index.html
|
||||
```
|
||||
|
||||
**状態の読み方:**
|
||||
|
||||
- 赤色 = 変更されたがステージングされていない
|
||||
- 緑色 = ステージングされた(コミット準備OK)
|
||||
- Untracked = Gitがまだ追跡していない新しいファイル
|
||||
|
||||
VSCodeでの確認:
|
||||
|
||||
- 左サイドバーの「ソース管理」アイコンをクリック
|
||||
@@ -122,6 +151,44 @@ git status
|
||||
git commit -m "初回コミット: プロジェクトのセットアップ"
|
||||
```
|
||||
|
||||
**💡 コマンドの詳細説明:**
|
||||
|
||||
**git addとは?**
|
||||
|
||||
```bash
|
||||
# 全てのファイルをステージングエリアに追加
|
||||
git add .
|
||||
|
||||
# 特定のファイルだけ追加
|
||||
git add README.md
|
||||
|
||||
# 特定の種類のファイルを追加
|
||||
git add *.js
|
||||
```
|
||||
|
||||
**ステージングエリアとは?**
|
||||
|
||||
- コミット前の「準備エリア」のようなもの
|
||||
- ここに追加したファイルだけがコミットされる
|
||||
- 間違えてaddした場合は`git reset`で取り消せる
|
||||
|
||||
**git commitとは?**
|
||||
|
||||
```bash
|
||||
# 基本形
|
||||
git commit -m "メッセージ"
|
||||
|
||||
# 詳細なメッセージを書きたい場合
|
||||
git commit # エディタが開く
|
||||
```
|
||||
|
||||
**良いコミットメッセージの例:**
|
||||
|
||||
- ✅ `feat: TODO追加機能を実装`
|
||||
- ✅ `fix: 空のTODOを追加できるバグを修正`
|
||||
- ❌ `更新` (何を更新したか不明)
|
||||
- ❌ `aaa` (意味がわからない)
|
||||
|
||||
##### VSCode GUI方式
|
||||
|
||||
1. ソース管理パネルを開く(Ctrl+Shift+G)
|
||||
@@ -142,6 +209,37 @@ git log --oneline
|
||||
git log --graph --oneline --all
|
||||
```
|
||||
|
||||
**💡 コマンドの詳細説明:**
|
||||
|
||||
**git logの様々な表示方法:**
|
||||
|
||||
```bash
|
||||
# 詳細表示(デフォルト)
|
||||
$ git log
|
||||
commit a1b2c3d4e5f6... # コミットID(SHA-1ハッシュ)
|
||||
Author: Your Name <email@example.com>
|
||||
Date: Mon Jan 15 10:30:00 2024 +0900
|
||||
|
||||
feat: TODO追加機能を実装
|
||||
|
||||
# 1行表示(簡潔)
|
||||
$ git log --oneline
|
||||
a1b2c3d feat: TODO追加機能を実装
|
||||
9876543 fix: バグ修正
|
||||
|
||||
# グラフ表示(ブランチが見える)
|
||||
$ git log --graph --oneline
|
||||
* a1b2c3d (HEAD -> main) feat: TODO追加機能を実装
|
||||
* 9876543 fix: バグ修正
|
||||
```
|
||||
|
||||
**便利なオプション:**
|
||||
|
||||
- `-n 5` - 最新の5件だけ表示
|
||||
- `--since="2 weeks ago"` - 2週間以内のコミット
|
||||
- `--author="Your Name"` - 特定の人のコミット
|
||||
- `--grep="fix"` - メッセージに"fix"を含む
|
||||
|
||||
VSCode:
|
||||
|
||||
- Git Graph拡張機能でビジュアル表示
|
||||
@@ -169,6 +267,42 @@ git branch
|
||||
git checkout -b feature/add-todo-edit
|
||||
```
|
||||
|
||||
**💡 コマンドの詳細説明:**
|
||||
|
||||
**ブランチとは?**
|
||||
|
||||
- 開発の「枝分かれ」を作る機能
|
||||
- mainブランチを安全に保ちながら、新機能を開発できる
|
||||
- 失敗しても元に戻せる
|
||||
|
||||
**git branchの表示:**
|
||||
|
||||
```bash
|
||||
$ git branch
|
||||
* main # *がついているのが現在のブランチ
|
||||
feature/todo-list
|
||||
feature/styling
|
||||
```
|
||||
|
||||
**git checkoutの使い方:**
|
||||
|
||||
```bash
|
||||
# 新しいブランチを作成して切り替え(一番よく使う)
|
||||
git checkout -b feature/new-feature
|
||||
|
||||
# 既存のブランチに切り替え
|
||||
git checkout main
|
||||
|
||||
# ブランチを作成だけ(切り替えない)
|
||||
git branch feature/test
|
||||
```
|
||||
|
||||
**ブランチ名のルール(例):**
|
||||
|
||||
- `feature/機能名` - 新機能開発
|
||||
- `fix/バグ名` - バグ修正
|
||||
- `refactor/内容` - コード整理
|
||||
|
||||
VSCode:
|
||||
|
||||
- ステータスバー左下のブランチ名をクリック
|
||||
@@ -186,6 +320,44 @@ git checkout main
|
||||
git merge feature/add-todo-edit
|
||||
```
|
||||
|
||||
**💡 コマンドの詳細説明:**
|
||||
|
||||
**マージとは?**
|
||||
|
||||
- 別ブランチの変更を現在のブランチに統合すること
|
||||
- 枝分かれした開発を一つにまとめる
|
||||
|
||||
**マージの流れ:**
|
||||
|
||||
```bash
|
||||
# 1. 現在のブランチを確認
|
||||
git branch
|
||||
feature/add-todo-edit
|
||||
* main
|
||||
|
||||
# 2. マージ実行
|
||||
git merge feature/add-todo-edit
|
||||
Updating a1b2c3d..e5f6g7h
|
||||
Fast-forward # 早送りマージ(コンフリクトなし)
|
||||
src/app/page.tsx | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
# 3. マージ後の確認
|
||||
git log --oneline --graph -5
|
||||
```
|
||||
|
||||
**Fast-forwardマージとは?**
|
||||
|
||||
- コンフリクトがないシンプルなマージ
|
||||
- mainブランチがただ「進む」だけ
|
||||
|
||||
**マージ後のブランチ削除:**
|
||||
|
||||
```bash
|
||||
# 不要になったブランチを削除
|
||||
git branch -d feature/add-todo-edit
|
||||
```
|
||||
|
||||
VSCodeでのマージ:
|
||||
|
||||
1. Git Graphで視覚的にブランチを確認
|
||||
@@ -356,11 +528,76 @@ git config --global alias.lg "log --graph --oneline --all"
|
||||
- **問題**: Windows側のパスとWSL側のパスの混同
|
||||
- **対策**: 常にWSL側で作業、`pwd`でパス確認
|
||||
|
||||
**💡 具体的な例と解決法:**
|
||||
|
||||
```bash
|
||||
# パスの確認方法
|
||||
$ pwd
|
||||
/mnt/c/Users/... # ❌ Windows側(遅い)
|
||||
/home/username/... # ✅ WSL側(速い)
|
||||
|
||||
# ホームディレクトリに移動
|
||||
cd ~
|
||||
|
||||
# Windows側からWSL側にファイルをコピー
|
||||
cp -r /mnt/c/Users/yourname/projects/todo-app ~/projects/
|
||||
```
|
||||
|
||||
**VSCodeでの確認方法:**
|
||||
|
||||
- 左下に`WSL: Ubuntu`と表示されているか確認
|
||||
- ターミナルで`pwd`を実行してパスを確認
|
||||
|
||||
### 2. 改行コードの不一致
|
||||
|
||||
- **問題**: WindowsのCRLFとLinuxのLFの混在
|
||||
- **対策**: `.gitattributes`で統一、VSCodeの設定で`LF`に固定
|
||||
|
||||
**💡 詳細な解決方法:**
|
||||
|
||||
**エラーの例:**
|
||||
|
||||
```bash
|
||||
$ git add .
|
||||
$ git status
|
||||
warning: LF will be replaced by CRLF in src/app/page.tsx.
|
||||
The file will have its original line endings in your working directory
|
||||
```
|
||||
|
||||
**解決手順:**
|
||||
|
||||
1. **Gitの設定を変更**
|
||||
|
||||
```bash
|
||||
# WSL側で実行
|
||||
git config --global core.autocrlf input
|
||||
```
|
||||
|
||||
2. **`.gitattributes`ファイルを作成**
|
||||
|
||||
```bash
|
||||
echo "* text=auto eol=lf" > .gitattributes
|
||||
git add .gitattributes
|
||||
git commit -m "fix: 改行コードをLFに統一"
|
||||
```
|
||||
|
||||
3. **既存ファイルの改行コードを修正**
|
||||
|
||||
```bash
|
||||
# 全ファイルの改行コードをリセット
|
||||
git rm --cached -r .
|
||||
git reset --hard
|
||||
```
|
||||
|
||||
4. **VSCodeの設定を変更**
|
||||
|
||||
```json
|
||||
// .vscode/settings.json
|
||||
{
|
||||
"files.eol": "\n" // LFに固定
|
||||
}
|
||||
```
|
||||
|
||||
### 3. VSCodeが重い
|
||||
|
||||
- **問題**: Windows側のファイルをWSL経由で編集
|
||||
@@ -371,6 +608,88 @@ git config --global alias.lg "log --graph --oneline --all"
|
||||
- **問題**: HTTPSでのpush時に認証失敗
|
||||
- **対策**: SSH接続の使用、または認証トークンの設定
|
||||
|
||||
**💡 詳細な解決方法:**
|
||||
|
||||
**エラーの例:**
|
||||
|
||||
```bash
|
||||
$ git push origin main
|
||||
Username for 'https://gitea.example.com': yourname
|
||||
Password for 'https://yourname@gitea.example.com':
|
||||
remote: Invalid username or password.
|
||||
fatal: Authentication failed
|
||||
```
|
||||
|
||||
**解決方法1:SSHに切り替える(推奨)**
|
||||
|
||||
```bash
|
||||
# 1. 現在のリモートURLを確認
|
||||
git remote -v
|
||||
|
||||
# 2. HTTPSからSSHに変更
|
||||
git remote set-url origin git@gitea.example.com:username/todo-app.git
|
||||
|
||||
# 3. SSH鍵が設定されているか確認
|
||||
ssh -T git@gitea.example.com
|
||||
```
|
||||
|
||||
**解決方法2:アクセストークンを使う**
|
||||
|
||||
1. Giteaでアクセストークンを生成
|
||||
- 設定 → アプリケーション → アクセストークンを生成
|
||||
|
||||
2. 認証情報を保存
|
||||
|
||||
```bash
|
||||
# 認証情報ヘルパーを設定
|
||||
git config --global credential.helper store
|
||||
|
||||
# 次回のpush時にユーザー名とトークンを入力
|
||||
# パスワードの代わりにアクセストークンを使用
|
||||
```
|
||||
|
||||
### 5. ファイルが表示されない/消えた
|
||||
|
||||
**💡 よくあるシナリオと解決法:**
|
||||
|
||||
**ケース1:.gitignoreに追加されている**
|
||||
|
||||
```bash
|
||||
# .gitignoreの内容を確認
|
||||
cat .gitignore
|
||||
|
||||
# 特定のファイルがgitに追跡されているか確認
|
||||
git ls-files | grep "filename"
|
||||
|
||||
# .gitignoreされているファイルを強制的に追加
|
||||
git add -f filename
|
||||
```
|
||||
|
||||
**ケース2:間違えて削除した**
|
||||
|
||||
```bash
|
||||
# 削除したファイルを復元
|
||||
git checkout HEAD -- filename
|
||||
|
||||
# または、特定のコミットから復元
|
||||
git checkout abc123 -- filename
|
||||
```
|
||||
|
||||
### 6. コミットメッセージを間違えた
|
||||
|
||||
**💡 修正方法:**
|
||||
|
||||
```bash
|
||||
# 直前のコミットメッセージを修正
|
||||
git commit --amend -m "新しいメッセージ"
|
||||
|
||||
# エディタで編集
|
||||
git commit --amend
|
||||
|
||||
# 注意:すでにpushした場合は強制pushが必要(推奨しない)
|
||||
# git push --force-with-lease origin main
|
||||
```
|
||||
|
||||
## 実践演習
|
||||
|
||||
### 演習1: TODOアプリの履歴管理
|
||||
@@ -411,6 +730,34 @@ feat: TODO編集機能を追加
|
||||
変更
|
||||
```
|
||||
|
||||
### 💡 コミットメッセージのフォーマット
|
||||
|
||||
**基本形:**
|
||||
|
||||
```
|
||||
<タイプ>: <概要>
|
||||
|
||||
<詳細説明(オプション)>
|
||||
```
|
||||
|
||||
**タイプの種類:**
|
||||
|
||||
- `feat`: 新機能
|
||||
- `fix`: バグ修正
|
||||
- `docs`: ドキュメント
|
||||
- `style`: コードの意味に影響しない変更
|
||||
- `refactor`: コードの改善
|
||||
- `test`: テスト追加・修正
|
||||
- `chore`: ビルドプロセスや補助ツールの変更
|
||||
|
||||
**例:**
|
||||
|
||||
```bash
|
||||
git commit -m "feat: TODOのフィルタリング機能を追加"
|
||||
git commit -m "fix: 空のTODOを追加できるバグを修正"
|
||||
git commit -m "docs: READMEにインストール手順を追加"
|
||||
```
|
||||
|
||||
## VSCode ショートカット集
|
||||
|
||||
| 操作 | ショートカット |
|
||||
@@ -433,12 +780,73 @@ wsl --list --verbose
|
||||
cd ~/projects # Windows側ではなくWSL側で作業
|
||||
```
|
||||
|
||||
**💡 詳細な解決方法:**
|
||||
|
||||
**原因:** Windows側のファイルをWSL経由でアクセスすると遅い
|
||||
|
||||
```bash
|
||||
# ❌ 遅いパス(Windows側)
|
||||
cd /mnt/c/Users/yourname/projects/
|
||||
|
||||
# ✅ 速いパス(WSL側)
|
||||
cd ~/projects/
|
||||
|
||||
# パフォーマンス比較
|
||||
time git status # 実行時間を計測
|
||||
```
|
||||
|
||||
**他の改善策:**
|
||||
|
||||
1. Windows Defenderの除外フォルダにWSLを追加
|
||||
2. `.gitconfig`に以下を追加:
|
||||
|
||||
```
|
||||
[core]
|
||||
preloadindex = true
|
||||
fscache = true
|
||||
```
|
||||
|
||||
### VSCodeがWSLに接続できない
|
||||
|
||||
1. WSL拡張機能の再インストール
|
||||
2. WSLの再起動: `wsl --shutdown`
|
||||
3. VSCodeの再起動
|
||||
|
||||
**💡 詳細な解決手順:**
|
||||
|
||||
**ステップ1:拡張機能の確認**
|
||||
|
||||
```bash
|
||||
# VSCodeで拡張機能を確認
|
||||
# Ctrl+Shift+X で拡張機能パネルを開く
|
||||
# "WSL" を検索してインストール済みか確認
|
||||
```
|
||||
|
||||
**ステップ2:WSLの再起動**
|
||||
|
||||
```powershell
|
||||
# PowerShellで実行(管理者権限)
|
||||
wsl --shutdown
|
||||
|
||||
# 再度WSLを起動
|
||||
wsl
|
||||
```
|
||||
|
||||
**ステップ3:コマンドラインからVSCodeを起動**
|
||||
|
||||
```bash
|
||||
# WSL内から実行
|
||||
cd ~/projects/todo-app
|
||||
code .
|
||||
```
|
||||
|
||||
**それでも動かない場合:**
|
||||
|
||||
```bash
|
||||
# WSL内でVSCode Serverを手動インストール
|
||||
wget -O- https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64 | tar -xz
|
||||
```
|
||||
|
||||
## 発展学習
|
||||
|
||||
1. **Git Flow**の理解と実践
|
||||
@@ -449,15 +857,138 @@ cd ~/projects # Windows側ではなくWSL側で作業
|
||||
|
||||
## 推奨リソース
|
||||
|
||||
### 📚 公式ドキュメント
|
||||
|
||||
- [Pro Git Book(日本語)](https://git-scm.com/book/ja/v2)
|
||||
- [Gitea公式ドキュメント](https://docs.gitea.io/)
|
||||
- [VSCode公式ドキュメント - WSL](https://code.visualstudio.com/docs/remote/wsl)
|
||||
- [Learn Git Branching(インタラクティブ学習)](https://learngitbranching.js.org/?locale=ja)
|
||||
|
||||
### 🎥 日本語の動画教材
|
||||
|
||||
- [【Git入門】Gitの基本からGitHubの使い方まで完全解説](https://www.youtube.com/watch?v=LDOR5HfI_sQ)
|
||||
- [【2024年版】VSCodeでGitを使う方法](https://www.youtube.com/watch?v=vMZ0C06soxA)
|
||||
- [WSL2環境での開発環境構築](https://www.youtube.com/watch?v=CULr6fEUvAo)
|
||||
- [Gitコマンド入門 - サルでもわかるGit入門](https://backlog.com/ja/git-tutorial/)
|
||||
|
||||
### 📖 日本語の参考記事・書籍
|
||||
|
||||
- [サルでもわかるGit入門](https://backlog.com/ja/git-tutorial/) - バックログの無料チュートリアル
|
||||
- [Gitのしくみを図解で理解する](https://qiita.com/rana_kualu/items/4d2d75c6813c05034765)
|
||||
- [いまさら聞けないGit入門](https://www.slideshare.net/matsukaz/git-28304397)
|
||||
- 書籍:「Gitが、おもしろいほどわかる本」(MdN)
|
||||
- 書籍:「エンジニアのためのGitの教科書」(翔泳社)
|
||||
|
||||
### 🛠️ 実践的な学習リソース
|
||||
|
||||
- [GitHub Skills](https://skills.github.com/) - GitHubのインタラクティブコース
|
||||
- [Git Cheat Sheet (日本語)](https://training.github.com/downloads/ja/github-git-cheat-sheet/) - コマンド一覧
|
||||
- [Gitea Demo](https://try.gitea.io/) - Giteaを試せるデモサイト
|
||||
|
||||
### 💻 WSL関連リソース
|
||||
|
||||
- [Microsoft WSL公式ドキュメント](https://learn.microsoft.com/ja-jp/windows/wsl/)
|
||||
- [WSL2で作るWindows開発環境](https://zenn.dev/ryuu/articles/wsl2-dev-setup)
|
||||
- [Windows Terminalの使い方](https://forest.watch.impress.co.jp/docs/serial/yajiuma/1265263.html)
|
||||
|
||||
## 📦 よくあるGitシナリオ集
|
||||
|
||||
### シナリオ1:変更を元に戻したい
|
||||
|
||||
```bash
|
||||
# まだコミットしていない変更を全て取り消す
|
||||
git checkout -- .
|
||||
|
||||
# 特定のファイルだけ元に戻す
|
||||
git checkout -- src/app/page.tsx
|
||||
|
||||
# ステージングした変更を取り消す
|
||||
git reset HEAD filename
|
||||
```
|
||||
|
||||
### シナリオ2:コミット履歴をきれいにしたい
|
||||
|
||||
```bash
|
||||
# 直前のコミットと統合(コミットをまとめる)
|
||||
git reset --soft HEAD~1
|
||||
git commit -m "整理されたメッセージ"
|
||||
|
||||
# 注意:すでにpushした場合は他の人に影響するため避ける
|
||||
```
|
||||
|
||||
### シナリオ3:作業中に別の作業が必要になった
|
||||
|
||||
```bash
|
||||
# 現在の作業を一時保存
|
||||
git stash save "途中のTODO編集機能"
|
||||
|
||||
# 別のブランチで緊急作業
|
||||
git checkout -b hotfix/urgent-bug
|
||||
# ... 作業 ...
|
||||
git commit -m "fix: 緊急バグ修正"
|
||||
|
||||
# 元のブランチに戻って作業再開
|
||||
git checkout feature/todo-edit
|
||||
git stash pop
|
||||
```
|
||||
|
||||
## 👨🏫 学習のアドバイス
|
||||
|
||||
### Git初心者が陥りやすい罠
|
||||
|
||||
1. **いきなりmainブランチで作業**
|
||||
- 必ずブランチを作成してから作業
|
||||
- mainブランチは「完成品」を置く場所
|
||||
|
||||
2. **コミットメッセージが適当**
|
||||
- 「あとで見る自分」のために丁寧に書く
|
||||
- 「何を」「なぜ」変更したかを記載
|
||||
|
||||
3. **pushしてからミスに気づく**
|
||||
- push前に`git log`で確認
|
||||
- `git diff origin/main`で差分を確認
|
||||
|
||||
### 効率的な学習方法
|
||||
|
||||
1. **コマンドとGUIを両方使う**
|
||||
- 基本はVSCodeのGUIでOK
|
||||
- 複雑な操作はコマンドを学ぶ
|
||||
|
||||
2. **小さなコミットを心がける**
|
||||
- 1機能1コミット
|
||||
- 後から振り返りやすい
|
||||
|
||||
3. **エラーを恐れない**
|
||||
- Gitは「元に戻す」が得意
|
||||
- 大抵のミスは修復可能
|
||||
|
||||
### 次のステップ
|
||||
|
||||
1. **ブランチ戦略を学ぶ**
|
||||
- Git Flow
|
||||
- GitHub Flow
|
||||
- GitLab Flow
|
||||
|
||||
2. **チーム開発のルール**
|
||||
- コードレビュー
|
||||
- コミットメッセージ規約
|
||||
- ブランチ保護
|
||||
|
||||
3. **自動化を学ぶ**
|
||||
- Git Hooks
|
||||
- CI/CDパイプライン
|
||||
|
||||
## まとめ
|
||||
|
||||
WSL+VSCode環境でのGit/Gitea学習は、Windows環境でLinuxライクな開発を可能にします。VSCodeの強力なGit統合機能を活用しながら、コマンドラインでの操作も習得することで、柔軟な開発スタイルを身につけることができます。
|
||||
|
||||
**大切なのは:**
|
||||
|
||||
- 🔄 失敗を恐れず、何度も試す
|
||||
- 📝 学んだことをメモする
|
||||
- 🤝 わからないことは質問する
|
||||
- 🎯 小さな目標から始める
|
||||
|
||||
---
|
||||
|
||||
このカリキュラムは、TODOアプリ開発カリキュラムと連携して使用することを想定しています。
|
||||
|
||||
@@ -34,6 +34,50 @@
|
||||
- JSXの基本文法
|
||||
- 型定義の初歩(stringやnumberの使い方)
|
||||
|
||||
**💡 詳細な実装手順:**
|
||||
|
||||
1. **新しいコンポーネントファイルを作成**
|
||||
|
||||
```typescript
|
||||
// src/app/components/HelloWorld.tsx
|
||||
// Reactコンポーネントの基本形
|
||||
export default function HelloWorld() {
|
||||
return (
|
||||
<div className="p-4 bg-blue-100 rounded">
|
||||
<h2 className="text-xl font-bold">Hello World!</h2>
|
||||
<p className="text-gray-700">Reactコンポーネントの第一歩です</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**解説:**
|
||||
|
||||
- `export default function` - このコンポーネントを他のファイルから使えるようにする
|
||||
- JSXは見た目はHTMLに似ているが、実はJavaScriptの拡張構文
|
||||
- `className` - HTMLのclassの代わりに使用(JavaScriptの予約語と競合を避けるため)
|
||||
|
||||
2. **コンポーネントを使ってみる**
|
||||
|
||||
```typescript
|
||||
// src/app/page.tsx
|
||||
import HelloWorld from './components/HelloWorld';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<main className="min-h-screen p-8">
|
||||
<h1 className="text-3xl font-bold mb-4">私のTODOアプリ</h1>
|
||||
<HelloWorld />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**エラーが出た場合:**
|
||||
|
||||
- `Cannot find module` → importパスを確認(`./components/HelloWorld`)
|
||||
- `'HelloWorld' is not defined` → importし忘れていないか確認
|
||||
|
||||
### Phase 2: TODOアプリの骨組み作成 (3-4時間)
|
||||
|
||||
#### Step 2.1: UIコンポーネントの作成
|
||||
@@ -63,18 +107,203 @@ type Todo = {
|
||||
- 新しいTODOの作成
|
||||
- リストへの反映
|
||||
|
||||
**💡 詳細な実装と解説:**
|
||||
|
||||
```typescript
|
||||
// TODO追加関数の実装
|
||||
const addTodo = () => {
|
||||
// 空の入力をチェック(バリデーション)
|
||||
if (inputValue.trim() === '') {
|
||||
alert('TODOを入力してください');
|
||||
return;
|
||||
}
|
||||
|
||||
// 新しいTODOオブジェクトを作成
|
||||
const newTodo: Todo = {
|
||||
id: Date.now(), // 簡易的なID生成(本番ではuuidを推奨)
|
||||
text: inputValue,
|
||||
completed: false
|
||||
};
|
||||
|
||||
// 状態を更新(重要:配列をコピーして新しい配列を作る)
|
||||
setTodos([...todos, newTodo]);
|
||||
|
||||
// 入力欄をクリア
|
||||
setInputValue('');
|
||||
};
|
||||
|
||||
// フォームで使う場合
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault(); // ページのリロードを防ぐ
|
||||
addTodo();
|
||||
};
|
||||
|
||||
// JSX部分
|
||||
<form onSubmit={handleSubmit} className="flex gap-2 mb-4">
|
||||
<input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
className="flex-1 border p-2 rounded"
|
||||
placeholder="TODOを入力してEnterキー"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
|
||||
>
|
||||
追加
|
||||
</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
**なぜこのように書くのか:**
|
||||
|
||||
- `trim()` - 空白だけの入力を防ぐ
|
||||
- `Date.now()` - ミリ秒単位のタイムスタンプでIDを生成(簡易版)
|
||||
- `[...todos, newTodo]` - スプレッド構文で既存の配列をコピーして新しい要素を追加
|
||||
- `e.preventDefault()` - formのデフォルト動作(ページリロード)を止める
|
||||
|
||||
#### Step 3.2: TODO完了機能
|
||||
|
||||
- チェックボックスの実装
|
||||
- 完了状態の切り替え
|
||||
- 条件付きスタイリング
|
||||
|
||||
**💡 詳細な実装と解説:**
|
||||
|
||||
```typescript
|
||||
// 完了状態を切り替える関数
|
||||
const toggleTodo = (id: number) => {
|
||||
// mapを使って新しい配列を作成(イミュータビリティ)
|
||||
const updatedTodos = todos.map(todo => {
|
||||
if (todo.id === id) {
|
||||
// 該当するTODOを見つけたら、completedを反転
|
||||
return { ...todo, completed: !todo.completed };
|
||||
}
|
||||
return todo; // それ以外はそのまま
|
||||
});
|
||||
|
||||
setTodos(updatedTodos);
|
||||
};
|
||||
|
||||
// TODOリストの表示部分
|
||||
<ul className="space-y-2">
|
||||
{todos.map((todo) => (
|
||||
<li
|
||||
key={todo.id}
|
||||
className="flex items-center gap-3 p-3 border rounded hover:bg-gray-50"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={todo.completed}
|
||||
onChange={() => toggleTodo(todo.id)}
|
||||
className="w-5 h-5 cursor-pointer"
|
||||
/>
|
||||
<span
|
||||
className={`flex-1 ${todo.completed ? 'line-through text-gray-500' : ''}`}
|
||||
>
|
||||
{todo.text}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
```
|
||||
|
||||
**解説:**
|
||||
|
||||
- `map` - 配列の各要素を変換して新しい配列を作る
|
||||
- `{ ...todo, completed: !todo.completed }` - スプレッド構文でtodoをコピーし、completedだけ上書き
|
||||
- `checked={todo.completed}` - チェックボックスの状態をデータと同期
|
||||
- `line-through` - 完了時に打ち消し線を表示(Tailwind CSSのクラス)
|
||||
|
||||
**よくあるミス:**
|
||||
|
||||
```typescript
|
||||
// ❌ これは動かない!直接配列を変更している
|
||||
const todo = todos.find(t => t.id === id);
|
||||
todo.completed = !todo.completed; // Reactが変更を検知できない
|
||||
setTodos(todos); // 同じ配列をセットしても再レンダリングされない
|
||||
```
|
||||
|
||||
#### Step 3.3: TODO削除機能
|
||||
|
||||
- 削除ボタンの追加
|
||||
- 配列からの要素削除
|
||||
- 確認ダイアログ(オプション)
|
||||
|
||||
**💡 詳細な実装と解説:**
|
||||
|
||||
```typescript
|
||||
// 削除関数
|
||||
const deleteTodo = (id: number) => {
|
||||
// 確認ダイアログを表示(オプション)
|
||||
if (confirm('本当に削除しますか?')) {
|
||||
// filterを使って該当ID以外の要素で新しい配列を作成
|
||||
const filteredTodos = todos.filter(todo => todo.id !== id);
|
||||
setTodos(filteredTodos);
|
||||
}
|
||||
};
|
||||
|
||||
// TODOリストに削除ボタンを追加
|
||||
<li className="flex items-center gap-3 p-3 border rounded hover:bg-gray-50">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={todo.completed}
|
||||
onChange={() => toggleTodo(todo.id)}
|
||||
className="w-5 h-5 cursor-pointer"
|
||||
/>
|
||||
<span className={`flex-1 ${todo.completed ? 'line-through text-gray-500' : ''}`}>
|
||||
{todo.text}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => deleteTodo(todo.id)}
|
||||
className="text-red-500 hover:text-red-700 px-2 py-1 text-sm"
|
||||
>
|
||||
削除
|
||||
</button>
|
||||
</li>
|
||||
```
|
||||
|
||||
**解説:**
|
||||
|
||||
- `filter` - 条件に合う要素だけで新しい配列を作成
|
||||
- `todo.id !== id` - 削除対象以外の要素を残す
|
||||
- `confirm()` - ブラウザの確認ダイアログ(true/falseを返す)
|
||||
|
||||
**カスタム確認ダイアログの例:**
|
||||
|
||||
```typescript
|
||||
// 状態でモーダルを管理
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||
const [deletingId, setDeletingId] = useState<number | null>(null);
|
||||
|
||||
// 削除モーダルコンポーネント
|
||||
{showDeleteModal && (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
|
||||
<div className="bg-white p-6 rounded-lg">
|
||||
<p className="mb-4">本当に削除しますか?</p>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={() => {
|
||||
if (deletingId) deleteTodo(deletingId);
|
||||
setShowDeleteModal(false);
|
||||
}}
|
||||
className="bg-red-500 text-white px-4 py-2 rounded"
|
||||
>
|
||||
削除
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowDeleteModal(false)}
|
||||
className="bg-gray-300 px-4 py-2 rounded"
|
||||
>
|
||||
キャンセル
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
### Phase 4: 高度な機能 (3-4時間)
|
||||
|
||||
#### Step 4.1: TODO編集機能
|
||||
@@ -82,6 +311,106 @@ type Todo = {
|
||||
- インライン編集の実装
|
||||
- 保存とキャンセル処理
|
||||
|
||||
**💡 詳細な実装と解説:**
|
||||
|
||||
```typescript
|
||||
// 編集用の状態管理
|
||||
const [editingId, setEditingId] = useState<number | null>(null);
|
||||
const [editText, setEditText] = useState('');
|
||||
|
||||
// 編集開始関数
|
||||
const startEdit = (todo: Todo) => {
|
||||
setEditingId(todo.id);
|
||||
setEditText(todo.text);
|
||||
};
|
||||
|
||||
// 編集保存関数
|
||||
const saveEdit = () => {
|
||||
if (editText.trim() === '') {
|
||||
alert('TODOが空です');
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedTodos = todos.map(todo => {
|
||||
if (todo.id === editingId) {
|
||||
return { ...todo, text: editText };
|
||||
}
|
||||
return todo;
|
||||
});
|
||||
|
||||
setTodos(updatedTodos);
|
||||
setEditingId(null); // 編集モードを終了
|
||||
};
|
||||
|
||||
// 編集キャンセル関数
|
||||
const cancelEdit = () => {
|
||||
setEditingId(null);
|
||||
setEditText('');
|
||||
};
|
||||
|
||||
// TODOリストの表示部分
|
||||
{todos.map((todo) => (
|
||||
<li key={todo.id} className="flex items-center gap-3 p-3 border rounded">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={todo.completed}
|
||||
onChange={() => toggleTodo(todo.id)}
|
||||
className="w-5 h-5 cursor-pointer"
|
||||
/>
|
||||
|
||||
{editingId === todo.id ? (
|
||||
// 編集モード
|
||||
<input
|
||||
type="text"
|
||||
value={editText}
|
||||
onChange={(e) => setEditText(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') saveEdit();
|
||||
if (e.key === 'Escape') cancelEdit();
|
||||
}}
|
||||
className="flex-1 border p-1 rounded"
|
||||
autoFocus
|
||||
/>
|
||||
) : (
|
||||
// 通常モード
|
||||
<span
|
||||
onClick={() => startEdit(todo)}
|
||||
className={`flex-1 cursor-pointer ${todo.completed ? 'line-through text-gray-500' : ''}`}
|
||||
>
|
||||
{todo.text}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{editingId === todo.id ? (
|
||||
// 編集モードのボタン
|
||||
<div className="flex gap-1">
|
||||
<button onClick={saveEdit} className="text-green-600 text-sm">
|
||||
保存
|
||||
</button>
|
||||
<button onClick={cancelEdit} className="text-gray-600 text-sm">
|
||||
キャンセル
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
// 通常モードのボタン
|
||||
<button
|
||||
onClick={() => deleteTodo(todo.id)}
|
||||
className="text-red-500 hover:text-red-700 text-sm"
|
||||
>
|
||||
削除
|
||||
</button>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
```
|
||||
|
||||
**ポイント:**
|
||||
|
||||
- `editingId` - 現在編集中のTODOのIDを保持
|
||||
- `onKeyDown` - キーボードイベントでEnter/Escを検知
|
||||
- `autoFocus` - 編集開始時に自動的にフォーカス
|
||||
- 三項演算子 `? :` - 条件によって表示を切り替え
|
||||
|
||||
#### Step 4.2: フィルタリング機能
|
||||
|
||||
- All/Active/Completedの切り替え
|
||||
@@ -131,6 +460,66 @@ export default function Home() {
|
||||
const [todos, setTodos] = useState<Todo[]>([]);
|
||||
```
|
||||
|
||||
**💡 完全な実装例とコード解説:**
|
||||
|
||||
```typescript
|
||||
// src/app/page.tsx
|
||||
'use client'; // ← 重要!状態管理を使う時は必須
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
// TypeScriptの型定義
|
||||
// interfaceまたはtypeで定義可能
|
||||
type Todo = {
|
||||
id: number; // 一意の識別子
|
||||
text: string; // TODOの内容
|
||||
completed: boolean; // 完了状態
|
||||
};
|
||||
|
||||
export default function Home() {
|
||||
// useState フックの使い方
|
||||
// const [状態変数, 状態を更新する関数] = useState<型>(初期値);
|
||||
const [todos, setTodos] = useState<Todo[]>([]);
|
||||
|
||||
// 入力フォームの状態も管理
|
||||
const [inputValue, setInputValue] = useState<string>('');
|
||||
|
||||
return (
|
||||
<main className="min-h-screen p-8">
|
||||
<h1 className="text-3xl font-bold mb-8">TODOアプリ</h1>
|
||||
|
||||
{/* 入力フォーム */}
|
||||
<div className="mb-4">
|
||||
<input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
className="border p-2 rounded"
|
||||
placeholder="TODOを入力"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* TODOリスト表示 */}
|
||||
<ul className="space-y-2">
|
||||
{todos.map((todo) => (
|
||||
<li key={todo.id} className="p-2 border rounded">
|
||||
{todo.text}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**解説:**
|
||||
|
||||
- `'use client'` - クライアントサイドで実行するコンポーネントであることを宣言
|
||||
- `useState<Todo[]>([])` - 空の配列で初期化、型はTodoの配列
|
||||
- `onChange` - 入力が変更されるたびに実行される
|
||||
- `map` - 配列の各要素をJSXに変換
|
||||
- `key={todo.id}` - Reactが効率的に更新するために必要
|
||||
|
||||
## つまずきやすいポイントと対策
|
||||
|
||||
### 1. TypeScriptのエラー
|
||||
@@ -138,6 +527,43 @@ const [todos, setTodos] = useState<Todo[]>([]);
|
||||
- 型定義が分からない → 最初はanyを使い、後から具体的な型に修正
|
||||
- 型推論に頼る → VSCodeの補完機能を活用
|
||||
|
||||
**💡 よくあるTypeScriptエラーと解決策:**
|
||||
|
||||
```typescript
|
||||
// エラー例1: Parameter 'e' implicitly has an 'any' type
|
||||
// ❌ エラーが出るコード
|
||||
const handleChange = (e) => {
|
||||
setInputValue(e.target.value);
|
||||
};
|
||||
|
||||
// ✅ 解決策1: 型を明示的に指定
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setInputValue(e.target.value);
|
||||
};
|
||||
|
||||
// ✅ 解決策2: インラインで書く(型推論が効く)
|
||||
<input onChange={(e) => setInputValue(e.target.value)} />
|
||||
|
||||
// エラー例2: Object is possibly 'undefined'
|
||||
// ❌ エラーが出るコード
|
||||
const todo = todos.find(t => t.id === id);
|
||||
console.log(todo.text); // todoがundefinedの可能性
|
||||
|
||||
// ✅ 解決策: オプショナルチェイニング
|
||||
console.log(todo?.text);
|
||||
|
||||
// または条件分岐
|
||||
if (todo) {
|
||||
console.log(todo.text);
|
||||
}
|
||||
```
|
||||
|
||||
**VSCodeの便利機能:**
|
||||
|
||||
- 変数にカーソルを合わせると型が表示される
|
||||
- Ctrl+Space で補完候補を表示
|
||||
- エラーの上にカーソルを置くと「Quick Fix」が提案される
|
||||
|
||||
### 2. 状態更新のイミュータビリティ
|
||||
|
||||
- 配列の直接変更はNG → スプレッド構文やfilter/mapを使用
|
||||
@@ -191,11 +617,33 @@ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
|
||||
## 推奨リソース
|
||||
|
||||
### 📚 公式ドキュメント
|
||||
|
||||
- [Next.js公式ドキュメント](https://nextjs.org/docs)
|
||||
- [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
|
||||
- [React公式チュートリアル](https://react.dev/learn)
|
||||
- [Tailwind CSS公式ドキュメント](https://tailwindcss.com/docs)
|
||||
|
||||
### 🎥 日本語の動画教材
|
||||
|
||||
- [【2024年最新】React完全入門ガイド|Hooks、Next.js、TypeScriptまで](https://www.youtube.com/watch?v=TGiCr7S2E7E)
|
||||
- [Next.js入門 - App Routerを基礎から学ぶ](https://www.youtube.com/watch?v=BVq8n8tVNJg)
|
||||
- [TypeScript入門 完全版](https://www.youtube.com/watch?v=F9vzRz6jyRk)
|
||||
|
||||
### 📖 日本語の参考記事・書籍
|
||||
|
||||
- [サバイバルTypeScript](https://typescriptbook.jp/) - TypeScriptの実践的な解説
|
||||
- [React入門 TODOアプリ開発](https://zenn.dev/topics/react-todo) - Zennの関連記事集
|
||||
- [Next.js App Router入門](https://zenn.dev/hayato94087/articles/e9712c4ab7a8f1) - 詳細な解説記事
|
||||
- 書籍:「React実践入門」(技術評論社)
|
||||
- 書籍:「TypeScript実践プログラミング」(マイナビ出版)
|
||||
|
||||
### 🛠️ 実践的な学習リソース
|
||||
|
||||
- [React Tutorial: Tic-Tac-Toe(日本語版)](https://ja.react.dev/learn/tutorial-tic-tac-toe) - 公式チュートリアル
|
||||
- [TypeScript Playground](https://www.typescriptlang.org/play) - ブラウザで試せる
|
||||
- [StackBlitz](https://stackblitz.com/) - オンラインでNext.jsを試せる
|
||||
|
||||
## サポート方法
|
||||
|
||||
1. **ペアプログラミング**: 詰まったらすぐに質問
|
||||
@@ -206,3 +654,68 @@ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
---
|
||||
|
||||
このカリキュラムは柔軟に調整可能です。学習者のペースに合わせて進めてください。
|
||||
|
||||
## 👨🏫 学習の進め方アドバイス
|
||||
|
||||
### 初心者がつまずきやすいポイント
|
||||
|
||||
1. **エラーメッセージを恐れない**
|
||||
- エラーは学習のチャンス
|
||||
- エラーメッセージをしっかり読んでコピー&ペーストでGoogle検索
|
||||
|
||||
2. **小さく始める**
|
||||
- いきなり全部を理解しようとしない
|
||||
- まず動くものを作ってから理解を深める
|
||||
|
||||
3. **コードを写経する**
|
||||
- 最初はサンプルコードをそのまま写す
|
||||
- 動いたら少しずつ変更して実験
|
||||
|
||||
### 各Phaseの確認ポイント
|
||||
|
||||
#### Phase 1 終了時
|
||||
|
||||
- [ ] `npm run dev`でアプリが起動する
|
||||
- [ ] ブラウザに「Hello World」が表示される
|
||||
- [ ] コンポーネントを自分で作成できる
|
||||
|
||||
#### Phase 2 終了時
|
||||
|
||||
- [ ] TODOの入力フォームが表示される
|
||||
- [ ] TODOリストが表示される(まだ空でOK)
|
||||
- [ ] スタイルが適用されている
|
||||
|
||||
#### Phase 3 終了時
|
||||
|
||||
- [ ] TODOを追加できる
|
||||
- [ ] TODOを完了/未完了に切り替えられる
|
||||
- [ ] TODOを削除できる
|
||||
|
||||
## 🔥 FAQ(よくある質問)
|
||||
|
||||
### Q: `'use client'`を忘れてエラーが出ました
|
||||
|
||||
**A:** useStateなどのフックを使う時は、ファイルの先頭に`'use client'`が必要です。
|
||||
|
||||
### Q: 「Cannot find module」エラーが出ます
|
||||
|
||||
**A:** importのパスが間違っている可能性があります。`./`で始まる相対パスか、`@/`で始まるエイリアスを確認してください。
|
||||
|
||||
### Q: スタイルが適用されません
|
||||
|
||||
**A:** classNameを使っているか確認してください(classではなく)。また、Tailwind CSSのクラス名が正しいか公式ドキュメントで確認しましょう。
|
||||
|
||||
### Q: TODOが保存されずリロードすると消えます
|
||||
|
||||
**A:** Phase 4のLocal Storage実装まではこれが正常です。メモリ上にしかデータが保存されていません。
|
||||
|
||||
### Q: TypeScriptの型エラーが難しいです
|
||||
|
||||
**A:** 最初は`any`型を使ってもOKです。動くようになったら徐々に適切な型に置き換えていきましょう。
|
||||
|
||||
### Q: mapやfilterがよく分かりません
|
||||
|
||||
**A:** これらはJavaScriptの配列メソッドです。MDNの日本語ドキュメントで詳しく解説されています。
|
||||
|
||||
- [Array.prototype.map()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
|
||||
- [Array.prototype.filter()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
|
||||
|
||||
Reference in New Issue
Block a user