☹️

shadcn/uiのドロップダウンメニューの中にアラートダイアログを使うときの注意

2024/06/23に公開

Next.jsでshadcn/uiを使っている時にちょっと罠があったので共有しておきます。



問題はこんな感じのUIを作ってログアウトする時にダイアログを出してワンクッション挟もうと思ってたときに起こりました。

問題点

DropdownMenuContentをAlertDialogTriggerに指定していざ試してみたら、ダイアログが一瞬出るもののすぐに閉じられてしまいました。
おそらくradixの方のDropdownMenuの閉じるフラグとAlertDialogの閉じるフラグが同じことで起こってしまうのかなと思います。

解決方法

結論から言うと、DropdownMenuの中にAlertDialogを入れるのではなく、DropdownMenuをAlertDialogでラップしてTriggerのみ中にいれてあげれば解決しました。


問題のあったコード

return (
    <>
    <DropdownMenu>
        <DropdownMenuTrigger>
            <Button>開く</Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent>
            <DropdownMenuLabel>アカウント</DropdownMenuLabel>
            <DropdownMenuItem onClick={() => router.push("/")}>
                <Cog6ToothIcon />
                <span>アカウント設定</span>
            </DropdownMenuItem>
            <AlertDialog>
                <AlertDialogTrigger>
                    <DropdownMenuItem>
                        <ArrowLeftEndOnRectangleIcon />
                        <span>ログアウト</span>
                    </DropdownMenuItem>
                </AlertDialogTrigger>
                <AlertDialogContent>
                    <AlertDialogHeader>
                        <AlertDialogTitle>ログアウトしますか?</AlertDialogTitle>
                        <AlertDialogDescription>
                            説明がここに入ります。
                        </AlertDialogDescription>
                    </AlertDialogHeader>
                    <AlertDialogFooter>
                        <AlertDialogCancel>戻る</AlertDialogCancel>
                        <AlertDialogAction onClick={() => signOut()}>ログアウト</AlertDialogAction>
                    </AlertDialogFooter>
                    </AlertDialogContent>
            </AlertDialog>
        </DropdownMenuContent>
    </DropdownMenu>
    </>
)


解決方法

return(
    <>
    <AlertDialog>
        <DropdownMenu>
            <DropdownMenuTrigger>
                <Button>開く</Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent>
                <DropdownMenuLabel>アカウント</DropdownMenuLabel>
                <DropdownMenuItem onClick={() => router.push("/")}>
                    <Cog6ToothIcon />
                    <span>アカウント設定</span>
                </DropdownMenuItem>
                <AlertDialogTrigger>
                    <DropdownMenuItem>
                        <ArrowLeftEndOnRectangleIcon />
                        <span>ログアウト</span>
                    </DropdownMenuItem>
                </AlertDialogTrigger>
            </DropdownMenuContent>
        </DropdownMenu>
        <AlertDialogContent>
            <AlertDialogHeader>
            <AlertDialogTitle>ログアウトしますか?</AlertDialogTitle>
            <AlertDialogDescription>
                説明がここに入ります。
            </AlertDialogDescription>
            </AlertDialogHeader>
            <AlertDialogFooter>
            <AlertDialogCancel>戻る</AlertDialogCancel>
            <AlertDialogAction onClick={() => signOut()}>ログアウト</AlertDialogAction>
            </AlertDialogFooter>
        </AlertDialogContent>
    </AlertDialog>
    </>
)

Discussion