🧤

【React】「szhsin/react-menu」でリロードを発生させずリンク形式のメニューを実装

2022/11/11に公開

概要

Reactで、ドロップダウンのメニューを実装する際に使えるライブラリとしてszhsin/react-menuが挙げられます。このライブラリでメニューアイテムにhref属性が設定できるので、それでリンク形式のメニューにすることはできるのですが、こちらのドキュメント曰くリンク遷移時に、リロードが発生してしまうそう。
なるべくリロードは発生させたくないので、リンク要素をメニューアイテムのchildに入れる形にしたのですが、今度はメニューアイテムのpaddingが邪魔して、限られたエリアをクリックしなければいけない状態になりました。スタイルを別途調整が必要ということで、どう実装したかというのを今回メモ書きします。

前提等

  • 以下のイメージのようなメニューを実装します。クリックすると設定したパスにリロードなしに遷移して、メニューにフォーカスが当たったら行のどこをクリックしても遷移できるようにします。
  • Next.jsを使用してますので、リンクの要素にはnext/linkを使用しています。
  • Tailwindのclassを使用しています。

実装サンプル

import Link from "next/link";
import { Menu, MenuItem, MenuButton } from "@szhsin/react-menu";
import "@szhsin/react-menu/dist/index.css";
import "@szhsin/react-menu/dist/transitions/slide.css";

export default function SampleComponent() {
  // メニューアイテムのレンダリング用の関数
  function menuItemRender(href, label) {
    return (
      <MenuItem style={{ padding: "0 0 0 0" }}>
        <Link href={href} className="block">
          <span className="pl-6 mt-1 w-44 h-8">{label}</span>
        </Link>
      </MenuItem>
    );
  }

  return (
    <div className="ml-2">
      <Menu
        menuButton={
          <MenuButton>
            <svg
              xmlns="http://www.w3.org/2000/svg"
              className="w-10 h-10"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M4 6h16M4 12h16M4 18h16"
              />
            </svg>
          </MenuButton>
        }
        transition
        offsetY={10}
      >
        {menuItemRender("/", "Top")}
        {menuItemRender("/auth/login", "ログイン")}
        {menuItemRender("/auth/account_register", "会員登録")}
      </Menu>
    </div>
  );
}

Discussion