Published on

モーダルの開閉状態にURLを持たせる

Authors

モーダルが開いた状態のページを表示したい

Ximoto さんと話をしていて、モーダルの開閉状態をクエリで管理するような話題になりました。
そういえば自分では実装してなかったと思い、調べたらとても参考になる記事がありました。
モーダルの開閉状態を URL で管理する

page.tsx にモーダルの状態を持たせていて、なるほどなぁこれは良いものを見たぞと思い、記録を残しておきます。
azukiazusa1 さんありがとうございます。

こんなイメージでしょうか。
modalImage

ちょっといじって動的な 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;

走り書きですが後々役に立つかなと。
それではまた。