質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.34%
docker-compose

docker-composeとは、複数のコンテナで構成されるサービスを提供する手順を自動的し管理を簡単にするツール。composeファイルを使用しコマンド1回で設定した全サービスを作成・起動することが可能です。

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

294閲覧

next.jsでEditボタンを押すとloading...になってしまう。

gabakugik

総合スコア13

docker-compose

docker-composeとは、複数のコンテナで構成されるサービスを提供する手順を自動的し管理を簡単にするツール。composeファイルを使用しコマンド1回で設定した全サービスを作成・起動することが可能です。

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2024/08/14 17:47

編集2024/08/18 13:52

実現したいこと

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/ これをそのまんまコピペしました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

"use client"; import { useParams } from 'next/navigation'; import Link from 'next/link'; import EditTodoForm from '@/components/EditTodoForm'; const EditTodoPage = () => { // Use useParams to retrieve the id from the URL const { id } = useParams<{ id: string }>(); // 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;

これでいけました。
ありがとうございました。

投稿2024/08/19 13:20

編集2024/08/19 13:21
gabakugik

総合スコア13

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.34%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問