h-yabi2 / Next.js-MongoDB-TodoAPP

App Router, Server Actions, MongoDB学習
0 stars 0 forks source link

タスク作成機能の実装(useFormState, useFormStatus を使用) #2

Open h-yabi2 opened 3 weeks ago

h-yabi2 commented 3 weeks ago

src/actions/task.ts

"use server";

import { Task, TaskModel } from "@/models/task";
import { connectDB } from "@/utils/database";
import { redirect } from "next/navigation";

export interface FormState {
  error: string;
}

export const createTask = async (state: FormState, formData: FormData) => {
  const newTask: Task = {
    title: formData.get("title") as string,
    description: formData.get("description") as string,
    dueDate: formData.get("dueDate") as string,
    isCompleted: false,
  };

  try {
    await connectDB();
    await TaskModel.create(newTask);
  } catch (error) {
    state.error = "タスクの作成に失敗しました";
    return state;
  }

  redirect("/");
};

src/components/NewTaskForm/NewTaskForm.tsx

"use client";

import { createTask, FormState } from "@/actions/task";
import { use } from "react";
import { useFormState, useFormStatus } from "react-dom";

const NewTaskForm = () => {
  const initialState: FormState = {
    error: "",
  };
  const [state, formActions] = useFormState(createTask, initialState);

  const SubmitButton = () => {
    const { pending } = useFormStatus();
    return (
      <button
        type="submit"
        className="mt-8 py-2 w-full rounded-md text-white 
        bg-gray-800 hover:bg-gray-700 text-sm font-semibold shadow-sm disabled:opacity-50"
        disabled={pending}
      >
        Create
      </button>
    );
  };

  return (
    <div className="mt-10 mx-auto w-full max-w-sm">
      <form action={formActions}>
        ~
        <SubmitButton />
        {state.error && (
          <p className="mt-4 text-sm text-red-500">{state.error}</p>
        )}
      </form>
    </div>
  );
};

export default NewTaskForm;

作業コミット

h-yabi2 commented 3 weeks ago

該当箇所

Next-Tasks-10-27-2024_12_26_PM