実現したいこと
qiitaで一週間回答を求めたんですが....
答えにたどり着けず.....
解決したいこと
https://qiita.com/gabakugik/items/b0fcc09158d336e9e2a8
の続きです。
発生している問題・エラーメッセージ
updateボタンを押すとLoading画面になる。
該当のソースコード
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
"use client"; import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import useSWR from 'swr'; import Link from 'next/link'; import Todo from '@/components/Todo'; import { TodoType } from '@/types/Todo'; import axios from 'axios'; // Fetcher function for SWR const fetcher = (url: string) => axios.get(url).then(res => res.data); // Todo詳細ページを表示するコンポーネント const TodoDetail = ({ params }: { params: { id: string } }) => { // ルーティング情報を取得する const router = useRouter(); const { id } = params; // SWRを使ってデータを取得する const { data: todo, error } = useSWR<TodoType>(id ? `http://localhost:3000/todos/${id}` : null, fetcher); // エラーが発生した場合の処理 if (error) return <div>Failed to load</div>; // Todoを取得中の場合は「Loading...」を表示する if (!todo) return <div>Loading...</div>; return ( <div className="flex justify-center items-center"> <div className="flex flex-col space-y-6 w-3/4 max-w-lg pt-10"> <label className="block text-xl font-bold text-gray-700">Todo</label> <Todo todo={todo} /> <div className="flex justify-end"> <Link href={`/todos/${id}/`} className="mt-auto font-medium text-blue-600 hover:bg-blue-300 focus:outline-none mr-12" > Edit </Link> <Link href="/" className="mt-auto font-medium text-blue-600 hover:bg-blue-300 focus:outline-none" > Back </Link> </div> </div> </div> ); }; export default TodoDetail;
"use client" import React, { useEffect, useState } from 'react'; import { useRouter } from 'next/router'; import axios from 'axios'; type EditTodoFormProps = { id: number; }; // Todo を編集するフォーム const EditTodoForm = ({ id }: EditTodoFormProps) => { const router = useRouter(); // フォームの入力値を管理するstate const [title, setTitle] = useState(''); // フォームの入力値を管理するstate const [content, setContent] = useState(''); // idが変更されたら(=Todo編集ページを開いたら)、Todoを取得してフォームの初期値を設定する useEffect(() => { // idが存在しない場合は、処理を中断する const fetchTodo = async () => { try { // idを元にTodoを取得する const res = await axios.get(`http://localhost:3000/todos/${id}`); // フォームの初期値を設定する const { title, content } = res.data; setTitle(title); setContent(content); } catch (err) { console.log(err); } }; // idが存在する場合は、Todoを取得する if (id) { fetchTodo(); } }, [id]); // フォームの入力値を更新する関数 const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { // APIを呼び出して、Todoを更新する await axios.put(`http://localhost:3000/todos/${id}`, { todo: { title, content } }); // Todoの更新に成功したら、Todo詳細ページに遷移する router.push(`/todos/${id}`); } catch (error) { console.error(error); } }; return ( <div className="space-y-6 py-16"> <form onSubmit={handleSubmit} className="space-y-6" > <label className="block text-xl font-bold text-gray-700">Edit 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" > Update </button> </form> </div> ); }; export default EditTodoForm;
"use client" import { useRouter } from 'next/router'; import Link from 'next/link'; import EditTodoForm from '@/components/EditTodoForm'; const EditTodoPage = () => { // Next.js の useRouter を使って、URLのクエリパラメータを取得します const router = useRouter(); const { id } = router.query; // クエリパラメータが取得できるまで、Loading...を表示します if (!id) { return <div>Loading...</div>; } return ( <div className="flex justify-center items-center"> <div className="flex flex-col w-3/4 max-w-lg"> <EditTodoForm id={parseInt(id as string)} /> <Link href="/" className="ml-auto font-medium text-blue-600 hover:bg-blue-300 focus:outline-none" > Back </Link> </div> </div> ); }; ```/frontend/app/todos/[id]/edit/page.tsx "use client"; import { useSearchParams } from 'next/navigation'; import Link from 'next/link'; import EditTodoForm from '@/components/EditTodoForm'; const EditTodoPage = () => { // Use useSearchParams to retrieve the id from the URL const searchParams = useSearchParams(); const id = searchParams.get('id'); // Display loading state until id is available if (!id) { return <div>Loading...</div>; } return ( <div className="flex justify-center items-center"> <div className="flex flex-col w-3/4 max-w-lg"> <EditTodoForm id={parseInt(id)} /> <Link href="/" className="ml-auto font-medium text-blue-600 hover:bg-blue-300 focus:outline-none" > Back </Link> </div> </div> ); }; export default EditTodoPage;
### 試したこと https://musclecoding.com/next-js-rails-todo-tutorial/ これをそのまんまコピペしました。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。