下拉菜单内的 Shadcn 对话框自动关闭

JJ7*_*J77 7 javascript reactjs next.js

我在 next.js 13 项目中使用 shadcn。我想要一个带有编辑或删除条目选项的下拉菜单。当用户单击“删除”时,应弹出一个对话框并要求他们确认。但是,该对话框仅显示约 0.5 秒,然后与下拉菜单一起关闭。我怎样才能防止这种情况发生?

这是codesandbox 上的示例:Codesandbox

这是代码:

    <DropdownMenu>
      <DropdownMenuTrigger>
        <p>Trigger</p>
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        <Dialog>
          <DropdownMenuLabel>Edit Entry</DropdownMenuLabel>
          <DropdownMenuSeparator />
          <DropdownMenuItem
            onClick={() => conosle.log("Navigate to edit page")}
          >
            Edit
          </DropdownMenuItem>
          <DialogTrigger>
            <DropdownMenuItem>Delete</DropdownMenuItem>
          </DialogTrigger>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>Are you sure?</DialogTitle>
              <DialogDescription>
                Do you want to delete the entry? Deleting this entry cannot be
                undone.
              </DialogDescription>
            </DialogHeader>
            <DialogFooter>
              <DialogClose asChild>
                <Button variant="outline">Cancel</Button>
              </DialogClose>
              <Button>Delete</Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>
      </DropdownMenuContent>
    </DropdownMenu>
Run Code Online (Sandbox Code Playgroud)

Ahm*_*set 18

问题是什么?

当您单击任何 时<DropdownMenuItem />,它将触发操作(onClick)并关闭(卸载)其中<DropdownMenuContent />包含的内容<DialogContent />,因此它将随之卸载。

解决方案

1. 移动<DialogContent />外部<DropdownMenuContent />

// ...
export default function App() {
  return (
    <Dialog> {/*  The dialog provider outside of the DropdownMenuContent */}
      <DropdownMenu>
        <DropdownMenuTrigger>
          <p>Trigger</p>
        </DropdownMenuTrigger>
        <DropdownMenuContent>
          <DropdownMenuItem>
            <DialogTrigger>
              Open Popup
            </DialogTrigger>
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>
      {/*  DialogContent ouside of DropdownMenuContent */}
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Are you sure?</DialogTitle>
          <DialogDescription>
            Do you want to delete the entry? Deleting this entry cannot be
            undone.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <DialogClose asChild>
            <Button variant="outline">Cancel</Button>
          </DialogClose>
          <Button>Delete</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
Run Code Online (Sandbox Code Playgroud)

如果您有单个项目触发对话框,则此解决方案效果很好。但是如果有多个对话框怎么办?

2. 多个对话框

将对话框移到 之外<DropdownMenuContent />,为每个对话框创建一个状态:

const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false)
Run Code Online (Sandbox Code Playgroud)

然后删除任何<DialogTrigger />,添加 onClick 代替

<DropdownMenuItem onClick={() => setIsEditDialogOpen(true)}>Edit</DropdownMenuItem>
<DropdownMenuItem onClick={() => setIsDeleteDialogOpen(true)}>Delete</DropdownMenuItem>
Run Code Online (Sandbox Code Playgroud)

在您的对话框中添加

<Dialog open={isEditDialogOpen || isDeleteDialogOpen} 
        onOpenChange={isEditDialogOpen ? 
            setIsEditDialogOpen : setIsDeleteDialogOpen}>
...
</Dialog>
Run Code Online (Sandbox Code Playgroud)

如果您不想让它受控并且可以渲染两个触发按钮,则可以渲染两个单独的对话框:

// ...
export default function App() {
  return (
    <Dialog> {/*  The dialog provider outside of the DropdownMenuContent */}
      <DropdownMenu>
        <DropdownMenuTrigger>
          <p>Trigger</p>
        </DropdownMenuTrigger>
        <DropdownMenuContent>
          <DropdownMenuItem>
            <DialogTrigger>
              Open Popup
            </DialogTrigger>
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>
      {/*  DialogContent ouside of DropdownMenuContent */}
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Are you sure?</DialogTitle>
          <DialogDescription>
            Do you want to delete the entry? Deleting this entry cannot be
            undone.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <DialogClose asChild>
            <Button variant="outline">Cancel</Button>
          </DialogClose>
          <Button>Delete</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
Run Code Online (Sandbox Code Playgroud)