6️⃣

【Laravel10】 Inertia + React で「追加・変更・削除・閲覧」機能をつくる(その6)

2024/07/23に公開

概要

【Laravel10】 Inertia + React で「追加・変更・削除・閲覧」機能をつくる(その5)の続編です。
現在、削除以外の実装が完了してる状態です。今回はdeleteアクションを実装して、完了とします。

バージョン情報

その1から同じなので、割愛

PostController::deleteを実装

コントローラ側

app/UseCases/Post/DeleteAction.phpを編集

app/UseCases/Post/DeleteAction.php
<?php

namespace App\UseCases\Post;

use App\Http\Requests\Post\FindRequest;

class DeleteAction
{
    public function __invoke(FindRequest $request): void
    {
        $post = $request->findPost();

        $post->delete();
    }
}

app/Http/Controllers/PostController.phpを編集

app/Http/Controllers/PostController.php
<?php

namespace App\Http\Controllers;

use App\UseCases\Post\IndexAction;
use App\UseCases\Post\StoreAction;
use App\UseCases\Post\FindAction;
use App\UseCases\Post\UpdateAction;
use App\UseCases\Post\DeleteAction;
use App\Http\Requests\Post\StoreRequest;
use App\Http\Requests\Post\FindRequest;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;

class PostController extends Controller
{
    public function index(IndexAction $action): Response
    {
        return Inertia::render('Post/Index', $action());
    }

    public function new(): Response
    {
        return Inertia::render('Post/Create');
    }

    public function store(StoreRequest $request, StoreAction $action): RedirectResponse
    {
        $action($request);

        return redirect()->route('posts.view.index')->with([
            'message' => '登録が完了しました',
        ]);
    }

    public function show(FindRequest $request, FindAction $action): Response
    {
        return Inertia::render('Post/Show', $action($request));
    }

    public function edit(FindRequest $request, FindAction $action): Response
    {
        return Inertia::render('Post/Edit', $action($request));
    }

    public function update(FindRequest $request, UpdateAction $action): RedirectResponse
    {
        $action($request);

        return redirect()->route('posts.view.index')->with([
            'message' => '変更が完了しました',
        ]);
    }

    public function destroy(FindRequest $request, DeleteAction $action): RedirectResponse
    {
        $action($request);

        // ページ番号つきでリダイレクト
        return redirect()->route('posts.view.index', ['page' => $request->page])->with([
            'message' => '削除が完了しました',
        ]);
    }
}

resources/js/Pages/Post/Index.jsxを編集

resources/js/Pages/Post/Index.jsx
import React from "react";
import { Link, useForm } from '@inertiajs/react';
import Pagination from "@/Components/Pagination";

export default function Index(props) {
    const { delete: destroy } = useForm({
        page: props.posts.current_page, // リクエストボディにpageを追加
    });

    // Data
    const { message } = props;

    // Methods
    const onDelete = id => {

        if(confirm('削除します。よろしいですか?')) {

            const url = route('posts.input.destroy', id);

            destroy(url, { preserveScroll: true });

        }

    };

    return (
        <div className="p-5">
            <h1 className="font-bold">{props.title}</h1>
            {message && <div id="message" className="mt-2 text-green-700  bg-green-100 p-3 rounded-lg">{message}</div>}
            <div className="text-right p-3 mb-2">
                <Link className="text-white bg-green-700 rounded-lg text-sm px-4 py-2 mr-2" href={route('posts.view.new')}>+ 追加する</Link>
            </div>
            <table className="w-full bg-gray-100">
                <thead className="bg-blue-100">
                    <tr>
                        <th>ID</th>
                        <th>タイトル</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    {props.posts.data.map(post => (
                        <tr key={post.id}>
                            <td className="p-2 border">{post.title}</td>
                            <td className="p-2 border">{post.body}</td>
                            <td className="p-2 border">
                                <Link
                                    className="text-white bg-gray-400 rounded-lg text-sm px-4 py-2 mr-2"
                                    href={route('posts.view.show', post.id)}>
                                    確認
                                </Link>
                                <Link
                                    className="text-white bg-blue-700 rounded-lg text-sm px-4 py-2 mr-2"
                                    href={route('posts.view.edit', post.id)}>
                                    変更
                                </Link>
                                <button
                                    className="text-white bg-red-700 rounded-lg text-sm px-4 py-2 mr-2"
                                    onClick={() => onDelete(post.id)}>
                                    削除
                                </button>
                            </td>
                        </tr>
                    ))}
                </tbody>
            </table>

            <Pagination data={props.posts} />
        </div>
    );
}

確認

npm run dev をして、http://localhost/posts にアクセスして、任意の投稿で「削除」をクリックしてみてください。
削除が上手く機能していることが確認できます。

関連記事

Discussion