1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Vite × React × TypeScript】Chakra UI v3でDrawerメニューからの遷移時、メニューが閉じない事象の解消方法

Posted at

はじめに

お疲れ様です。りつです。

今回はChakra UI v3でドロワーを実装中に意図しない挙動になったので、その解決記事です。

問題

現在、以下のようなヘッダーメニューを作成中です。

image.png

画面右上のハンバーガーメニューのアイコンをクリックすると、以下の画像のようなドロワーメニューが表示されるのですが、メニュー(例えば「TOP」の部分)をクリックしてもドロワーメニューが閉じませんでした。
(遷移先のURLに遷移自体はしています)

image.png

ソースコード

src/components/organisms/layout/Hader.tsx
import React, { memo, useCallback, useState } from "react";
import { useNavigate } from "react-router";
import { Box, Flex, Heading, Link } from "@chakra-ui/react";
import { MenuDrawer } from "@/components/molecules/MenuDrawer";

export const Header: React.FC = memo(() => {
  const [ open, setOpen ] = useState(false);
  const navigate = useNavigate ();

  const onClickHome = useCallback(() => navigate('/home'), []);
  const onClickUserManagement = useCallback(() => navigate('/home/user_management'), []);
  const onClickSetting = useCallback(() => navigate('/home/setting'), []);

  return (
    <>
      <Flex
        as="nav"
        bg="teal.500"
        color="gray.50"
        align="center"
        justify="space-between"
        padding={{ base: 3, md: 5 }}
      >
        <Flex align="center" as="a" mr={8} _hover={{ cursor: "pointer" }} onClick={onClickHome}>
        <Heading as="h1" fontSize={{ base: "md", md: "lg" }}>
          ユーザー管理アプリ
        </Heading>
        </Flex>
        <Flex align="center" fontSize="sm" flexGrow={2} display={{ base: "none", md: "flex" }}>
          <Box pr={4}>
            <Link color="gray.50" onClick={onClickUserManagement}>ユーザー一覧</Link>
          </Box>
            <Link color="gray.50" onClick={onClickSetting}>設定</Link>
        </Flex>
        <MenuDrawer
          open={open}
          setOpen={setOpen}
          onClickHome={onClickHome}
          onClickUserManagement={onClickUserManagement}
          onClickSetting={onClickSetting}
        />
      </Flex>
    </>
  );
});
src/components/molecules/MenuDrawer.tsx
import React, { memo } from "react";
import { Button } from "@chakra-ui/react";
import {
  DrawerBackdrop,
  DrawerBody,
  DrawerContent,
  DrawerRoot,
  DrawerTrigger,
} from "@/components/ui/drawer"
import { MenuIconButton } from "@/components/atoms/button/MenuIconButton";

type Props = {
  open: boolean;
  setOpen: React.Dispatch<React.SetStateAction<boolean>>;
  onClickHome: () => void;
  onClickUserManagement: () => void;
  onClickSetting: () => void;
}

export const MenuDrawer: React.FC<Props> = memo((props) => {
  const { open, setOpen, onClickHome, onClickUserManagement, onClickSetting } = props;
  return (
    <DrawerRoot placement="start" size="xs" open={open} onOpenChange={(e) => setOpen(e.open)}>
      <DrawerBackdrop />
      <DrawerTrigger asChild>
        <MenuIconButton/>
      </DrawerTrigger>
      <DrawerContent>
        <DrawerBody p={0} bg="gray.100">
          <Button w="100%" bg="gray.100" color="gray.800" onClick={onClickHome}>TOP</Button>
          <Button w="100%" bg="gray.100" color="gray.800" onClick={onClickUserManagement}>ユーザー一覧</Button>
          <Button w="100%" bg="gray.100" color="gray.800" onClick={onClickSetting}>設定</Button>
        </DrawerBody>
      </DrawerContent>
    </DrawerRoot>
  );
});
src/components/atoms/button/MenuIconButton.tsx
import React, { memo } from "react";
import { IconButton } from "@chakra-ui/react";
import { RxHamburgerMenu } from "react-icons/rx";

export const MenuIconButton: React.FC = memo(React.forwardRef<HTMLButtonElement>((props, ref) => {
  return (
    <IconButton
      ref={ref}
      {...props}
      aria-label="メニューボタン"
      size="sm"
      bg="teal.500"
      display={{ base: "block", md: "none"}}
    >
      <RxHamburgerMenu />
    </IconButton>
  );
}));

解決方法

ページ遷移用のボタンを<DrawerActionTrigger>で囲むことで解消できました。

src/components/molecules/MenuDrawer.tsx
import React, { memo } from "react";
import { Button, DrawerActionTrigger } from "@chakra-ui/react";
import {
  DrawerBackdrop,
  DrawerBody,
  DrawerContent,
  DrawerRoot,
  DrawerTrigger,
} from "@/components/ui/drawer"
import { MenuIconButton } from "@/components/atoms/button/MenuIconButton";

type Props = {
  open: boolean;
  setOpen: React.Dispatch<React.SetStateAction<boolean>>;
  onClickHome: () => void;
  onClickUserManagement: () => void;
  onClickSetting: () => void;
}

export const MenuDrawer: React.FC<Props> = memo((props) => {
  const { open, setOpen, onClickHome, onClickUserManagement, onClickSetting } = props;
  return (
    <DrawerRoot placement="start" size="xs" open={open} onOpenChange={(e) => setOpen(e.open)}>
      <DrawerBackdrop />
      <DrawerTrigger asChild>
        <MenuIconButton/>
      </DrawerTrigger>
      <DrawerContent>
        <DrawerBody p={0} bg="gray.100">
          <DrawerActionTrigger asChild> {/* ボタンをDrawerActionTriggerで囲む */}
            <Button w="100%" bg="gray.100" color="gray.800" onClick={onClickHome}>TOP</Button>
          </DrawerActionTrigger>
          <DrawerActionTrigger asChild> {/* ボタンをDrawerActionTriggerで囲む */}
            <Button w="100%" bg="gray.100" color="gray.800" onClick={onClickUserManagement}>ユーザー一覧</Button>
          </DrawerActionTrigger>
          <DrawerActionTrigger asChild> {/* ボタンをDrawerActionTriggerで囲む */}
            <Button w="100%" bg="gray.100" color="gray.800" onClick={onClickSetting}>設定</Button>
          </DrawerActionTrigger>
        </DrawerBody>
      </DrawerContent>
    </DrawerRoot>
  );
});

おわりに

解決方法としてはシンプルでした。

今後もChakra UI v3については調べつつ実装していきたいと思います。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?