- Published on
モーダルの開閉状態にURLを持たせる
- Authors
- Name
- Naoya 'noine' Sato
- @noineniya
モーダルが開いた状態のページを表示したい
Ximoto さんと話をしていて、モーダルの開閉状態をクエリで管理するような話題になりました。
そういえば自分では実装してなかったと思い、調べたらとても参考になる記事がありました。
モーダルの開閉状態を URL で管理する
page.tsx にモーダルの状態を持たせていて、なるほどなぁこれは良いものを見たぞと思い、記録を残しておきます。
azukiazusa1 さんありがとうございます。
こんなイメージでしょうか。
ちょっといじって動的な URL にしてみる
ブログや Instagram のようなマイクロ SNS にも応用できるよう、動的な URL でモーダルの状態を維持できるようなものをメモしておきます。
※ディレクトリ構造は環境に合わせてください
モーダル自体のコンポーネント
modal.tsx
"use client";
import { Dialog } from "@mui/material";
import Link from "next/link";
import { useRouter } from "next/navigation";
// モーダルの開閉状態、動的な何かを受け取れるようにpropsを作っておく
export const Modal = ({ open, text }: { open: boolean; text: string | string[] | undefined }) => {
const router = useRouter();
return (
<>
// ダイアログが閉じたときにはモーダルが閉じた状態のページヘ遷移
// 仮に/modalがモーダルが閉じてリンク一覧が見えている状態
// /modal/[id]がモーダルが開いている状態のページとして作成
<Dialog open={open} onClose={() => router.push("/modal")}>
<h2>モーダルだよ</h2>
<p>{text}</p>
</Dialog>
</>
);
};
仮に動的なページになるようにリンクを沢山作ってみる。
modalHome.tsx
import Link from "next/link";
import { Modal } from "./modal";
const TodoList = async () => {
// 適当なリストを取得して動的なリンクを作る
const todos = await fetch("https://jsonplaceholder.typicode.com/todos");
const todosJson = await todos.json();
return (
<ul>
{todosJson.map((todo: any) => (
// 空白が入っていたので取り除く
<Link href={`/todos/add/${todo.title.replace(/\s/g, "")}`} key={todo.id}>
<li>{todo.title}</li>
</Link>
))}
</ul>
);
};
// page.tsxからモーダルの開閉状態をバケツリレーするためにpropsを設定
// それと動的な情報をモーダルにも送ってみる
export const ModalHome = ({
open,
text,
}: {
open: boolean;
text: string | string[] | undefined;
}) => {
return (
<div>
<h1>Modal Home</h1>
<Modal open={open} text={text} />
<TodoList />
</div>
);
};
モーダルが閉じた状態のページを作成。
page.tsx
import { ModalHome } from "../components/modal/modalHome";
export default function Home() {
return (
<>
// ここでモーダルの状態を入れる。textはまぁなんでも
<ModalHome open={false} text={"close"} />
</>
);
}
モーダルが開いた状態のページを作成。
/[id]/page.tsx
import { ModalHome } from "../../components/modal/modalHome";
// URLのパラメータを取得
const Idpage = ({ params }: { params: { id: string } }) => {
return (
<div>
<h1>{params.id}</h1>
// モーダルを開く
<ModalHome open={true} text={params.id} />
</div>
);
};
export default Idpage;
走り書きですが後々役に立つかなと。
それではまた。