0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Day22 — 投稿一覧APIを作成し、Reactで一覧表示する

Last updated at Posted at 2025-12-21

はじめに

Day21 では、

✅ React からログイン
✅ JWT を保存
✅ 認証付き API を呼び出す

ところまで到達しました。

今日はついに、

「ログイン後に何ができるアプリか」

を形にします。

今日のゴール

・投稿一覧 API を Laravel で作成する

・JWT 認証付きで一覧取得できる

・React で投稿一覧を表示する

・「API × SPA」の基本形を完成させる

今回作る機能

・ログイン済みユーザーのみ閲覧可能

・投稿の一覧を取得

・フロントでリスト表示

※ 作成・更新・削除は Day23 以降で実装します

投稿モデルの確認

php artisan make:model Post -m
Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body')->nullable();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->timestamps();
});
php artisan migrate

ルーティング定義

routes/api.php

Route::middleware('auth:api')->group(function () {
    Route::get('/posts', [PostController::class, 'index']);
});

コントローラ作成

php artisan make:controller PostController

投稿一覧 API(Laravel)

use App\Models\Post;

public function index()
{
    $posts = Post::with('user')
        ->latest()
        ->get();

    return response()->json([
        'status' => 'success',
        'data' => $posts
    ]);
}

なぜ認証必須にする?

・誰でも見られる API にしない

・ログイン後の世界を明確に分ける

・JWT の効果を体感するため

👉 「ログインしないと見られない」
は SPA の基本構造です。

Postman で動作確認

GET /api/posts
Authorization: Bearer xxx.yyy.zzz

レスポンスが返れば成功 🎉

React 側で一覧を取得する

import { useEffect, useState } from 'react';

const Posts = () => {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    const fetchPosts = async () => {
      const token = localStorage.getItem('token');

      const res = await fetch('http://localhost/api/posts', {
        headers: {
          Authorization: `Bearer ${token}`
        }
      });

      const data = await res.json();
      setPosts(data.data);
    };

    fetchPosts();
  }, []);

  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>
          <strong>{post.title}</strong>
        </li>
      ))}
    </ul>
  );
};

export default Posts;

useEffect の役割

useEffect(() => {
  fetchPosts();
}, []);

・初回表示時に API を呼ぶ

・無限ループ防止

・SPA の基本パターン

よくあるエラー

❌ 401 Unauthorized

・トークン未送信

・トークン期限切れ

👉 再ログインで解決

❌ posts.map がエラー

Cannot read property 'map'

👉 初期値を [] にしているか確認

表示を少し整える

{posts.length === 0 && <p>投稿がありません</p>}

UX が少し良くなります。

実装のポイント

・API は認証前提

・レスポンス形式を揃える

・フロントは data のみを見る

・ロジックは最小限に

今日のまとめ

・投稿一覧 API を実装した

・JWT 認証付きで取得できた

・React で一覧表示できた

・SPA アプリらしくなってきた

次回 Day23

CRUD が揃います。

Day23 — 投稿作成APIを実装し、Reactから投稿できるようにする

「読むだけ」から「使えるアプリ」へ進みます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?