【第4回】Wiki一覧と詳細画面を作る〜情報の整理と見返しやすさを意識して〜
20:00

こんにちは。前回は、個人向けアプリに追加したWiki機能のうち、「記事の登録・更新・削除」機能について紹介しました。 今回はその続きとして、「Wikiの一覧表示」と「詳細画面」の実装についてご紹介します。
パスワード管理の記事は以下を参照してください。

【第1回】なぜ自分でパスワード管理アプリを作ったのか?〜40代エンジニアの試行錯誤〜
【第1回】の記事は以下を参照してください。

【第1回】なぜWiki機能を追加しようと思ったのか?〜40代エンジニアがCodeXに挑む理由〜
【第2回】の記事は以下を参照してください。

【第2回】Wikiテーブルの追加とダッシュボードの改修
【第3回】の記事は以下を参照してください。

【第3回】Wiki記事の登録・更新機能を実装する〜個人アプリに柔軟な知識管理を〜
目次
一覧画面の実装 /app/src/app/wikis/page.tsx
Wiki記事が増えてきたとき、「どこに何を書いたか?」をすばやく把握できる一覧画面は不可欠です。
以下は一覧表示のコードです:
'use client';
import { useEffect, useState } from 'react';
import Link from 'next/link';
import type { Wiki } from '@/types/wiki';
const WikiListPage = () => {
const [wikis, setWikis] = useState<Wiki[] | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const load = async () => {
try {
const res = await fetch('/api/wiki');
if (!res.ok) throw new Error('読み込み失敗');
const data: Wiki[] = await res.json();
setWikis(data);
} catch (err) {
setError((err as Error).message);
}
};
load();
}, []);
if (error) return <div>読み込みエラー</div>;
if (!wikis) return <div>読み込み中...</div>;
return (
<div className="space-y-4">
<h1 className="text-2xl font-bold">Wiki一覧</h1>
<Link href="/wikis/new" className="bg-blue-500 text-white px-4 py-2 rounded">新規作成</Link>
<ul className="space-y-2">
{wikis.map((wiki) => (
<li key={wiki.id} className="border p-4 rounded">
<Link href={`/wikis/${wiki.id}`} className="font-semibold hover:underline">
{wiki.title}
</Link>
</li>
))}
</ul>
</div>
);
};
export default WikiListPage;
データ取得は useEffect + fetch で行い、状態管理はシンプルに useState で構成しています。 一覧から記事のタイトルをクリックすると、次に紹介する詳細ページへ遷移します。
詳細画面の実装 /app/src/app/wikis/[id]/page.tsx
一覧から記事タイトルをクリックすると、個別記事の詳細が確認できるようになっています。
'use client';
import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import type { Wiki } from '@/types/wiki';
const WikiDetailPage = ({ params }: { params: { id: string } }) => {
const router = useRouter();
const [wiki, setWiki] = useState<Wiki | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const load = async () => {
try {
const res = await fetch(`/api/wiki/${params.id}`);
if (!res.ok) throw new Error('読み込み失敗');
const data: Wiki = await res.json();
setWiki(data);
} catch (err) {
setError((err as Error).message);
}
};
load();
}, [params.id]);
if (error) return <div>読み込みエラー</div>;
if (!wiki) return <div>読み込み中...</div>;
return (
<div className="space-y-4">
<h1 className="text-2xl font-bold">{wiki.title}</h1>
<p className="whitespace-pre-wrap border p-4 rounded bg-white">{wiki.content}</p>
<button onClick={() => router.push(`/wikis/edit/${wiki.id}`)} className="bg-blue-500 text-white px-4 py-2 rounded">編集</button>
</div>
);
};
export default WikiDetailPage;
ポイント
- 記事の内容は whitespace-pre-wrap を使って改行を保持
- 更新・削除機能:app/wiki/edit/[id]/page.tsx
- 編集ボタンでそのまま更新画面へ遷移できる動線を確保
- 閲覧→編集→戻るの流れがスムーズになるよう意識しています。
自分専用Wikiを使ってみて
登録・更新・削除・一覧・詳細表示が一通り揃ったことで、「簡易Wiki」としての機能が整いました。 特にローカル環境で使える安心感と、「すぐに書ける・すぐに見返せる」気軽さが、日々の学びやメモを蓄積する強力な土台になってくれます。
次回予告:「使ってみて感じたことと今後の展望」
次回は、ここまで作ってきたWiki機能について、実際の使用感や気づいた改善点、そしてこれからどんな進化を考えているかをご紹介する予定です。
まとめ
今回は、Wiki機能の一覧表示と詳細画面の実装を通して、「情報を整理し、見返せる」仕組みを作りました。
ちょっとした思いつきや技術的なメモを、あとから振り返れる形で残す。 それが継続的な学びにもつながっていきます。
次回も引き続き、ゆるっと開発の記録を綴っていきます。
0 件のコメント:
コメントを投稿
コメントをお待ちしています。