0
0

Next.js×RailsTodo 作成機能の実装

Last updated at Posted at 2024-08-08

Todo作成機能を作る

前回のhttps://qiita.com/gabakugik/items/bd013dcc92fd64564139
続き

/backend/app/controllers/todos_controller.rb
class TodosController < ApplicationController
    
    def index
        # 日付が新しい順に10件まで取得する
        @todos = Todo.all.order(created_at: :desc).limit(10)
    
        render json: @todos
    
    end
    
    def show
    
        @todo = Todo.find(params[:id])

    render json: @todo
    end

    def create
          
        @todo = Todo.new(todo_params)
      
        if @todo.save
            render json: @todo, status: :created, location: @todo
          else
            render json: @todo.errors, status: :unprocessable_entity
          end
        end
      
        def update
          @todo = Todo.find(params[:id])
      
          if @todo.update(todo_params)
            render json: @todo
          else
            render json: @todo.errors, status: :unprocessable_entity
          end
        end

        def todo_params
          params.require(:todo).permit(:title, :content)
    end
end
/frontend/app/components/CreateTodoForm.tsx
"use client";

import { useState } from 'react';
import axios from 'axios';
import useSWR, { mutate } from 'swr';

// APIのエンドポイント
const API_URL = 'http://localhost:3000/todos';

// Fetcher関数
const fetcher = (url: string) => axios.get(url).then(res => res.data);

// Todoを作成するフォーム
const CreateTodoForm: React.FC = () => {
  // フォームの入力値を管理するstate
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');

  // SWRを使ってデータをフェッチ
  const { data, error } = useSWR(API_URL, fetcher);

  // フォームの入力値を更新する関数
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
      // APIを呼び出して、Todoを作成する
      await axios.post(API_URL, {
        todo: {
          title,
          content,
        },
      });

      // Todoの作成に成功したら、フォームの入力値をリセットする
      setTitle('');
      setContent('');

      // Todoの作成に成功したら画面を更新する(Todoを再取得するため)
      mutate(API_URL);
    } catch (error) {
      console.error(error);
    }
  };

  if (error) return <div>Failed to load todos</div>;
  if (!data) return <div>Loading...</div>;

  return (
    <div className="space-y-6 w-3/4 max-w-lg py-10">
      <form onSubmit={handleSubmit} className="space-y-6">
        <label className="block text-xl font-bold text-gray-700">New Todo</label>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
          placeholder="タイトル"
          className="block w-full py-2 pl-3 pr-4 text-base border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-gray-500 focus:border-gray-500 sm:text-sm"
        />
        <textarea
          value={content}
          onChange={(e) => setContent(e.target.value)}
          placeholder="本文"
          className="mt-1 block w-full border border-gray-300 rounded-md shadow-sm py-2 px-3 focus:outline-none focus:ring-gray-500 focus:border-gray-500 sm:text-sm"
        />
        <button
          type="submit"
          className="mt-3 ml-auto flex justify-center py-2 px-8 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
        >
          Create
        </button>
      </form>
    </div>
  );
};

export default CreateTodoForm;


/frontend/app/page.tsx

import Todos from '@/components/Todos';
import CreateTodoForm from '@/components/CreateTodoForm';
// トップページ
export default function Home() {
  return (
    <div className="flex flex-col justify-center items-center">
      <Todos />
      <CreateTodoForm />
    </div>
  );
}

これで完成。
localhost:3001でフォームがあり、追加できる。

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