英文:
why doesn't mui dialog close on button click?
问题 {#heading}
在我的React项目中,我有一个对话框,可以全屏打开,但在点击关闭图标按钮时无法关闭。以下是相关代码部分:
打开对话框的组件:
interface IContentCardProps {
content: IContentProps;
}
const ContentCard = ({ content }: IContentCardProps) => {
const { user } = useUser();
const [open, setOpen] = useState<boolean>(false);
return (
<Box
p={2}
height="300px"
maxWidth="250px"
display="flex"
flexDirection="column"
justifyContent="space-between"
border={`1px solid ${blue.main}`}
sx={{
cursor: "pointer",
":hover": { boxShadow: `0px 0px 3px 1px ${blue.main}` },
}}
onClick={() => setOpen(true)}
>
<Typography
variant="body1"
gutterBottom
fontWeight={700}
color={blue.main}
>
{content?.title}
</Typography>
<Typography
variant="caption"
marginBottom={1}
lineHeight={1.6}
textOverflow="ellipsis"
display="-webkit-box "
overflow="hidden"
sx={{ WebkitLineClamp: 8, WebkitBoxOrient: "vertical" }}
>
{content?.description}
</Typography>
<Box pt={1} display="flex" alignItems="center" borderTop={`1px solid ${grey.extraLight}`}>
<SvgIcon component={AccessTimeOutlinedIcon} sx={{ mr: 1 }} />
<Typography variant="caption" fontWeight={700}>
<span>{content?.duration}</span> min
</Typography>
</Box>
<ContentDialog open={open} setOpen={setOpen} />
</Box>
);
};
export default ContentCard;
对话框组件:
const Transition = forwardRef(function Transition(
props: TransitionProps & {
children: React.ReactElement;
},
ref: React.Ref<unknown>,
) {
return <Slide direction="left" ref={ref} {...props} />;
});
interface IContentDialogProps {
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
}
const ContentDialog = ({ open, setOpen }: IContentDialogProps) => {
return (
<>
<Dialog fullScreen open={open} onClose={() => setOpen(false)} TransitionComponent={Transition}>
<AppBar sx={{ position: "relative", backgroundColor: blue.main }}>
<Toolbar>
<IconButton edge="start" color="inherit" onClick={() => setOpen(false)} aria-label="close">
<CloseIcon />
</IconButton>
</Toolbar>
</AppBar>
<Box>content</Box>
</Dialog>
</>
);
};
在这里,setOpen
似乎在对话框上不起作用,我不知道为什么会这样。如果有人有任何想法,那就太好了!
英文:
In my React project I have a dialog that opens full screen but does not close when clicking on the close icon button. <br />
The component opening the Dialog :
interface IContentCardProps {
content: IContentProps;
}
const ContentCard = ({ content }: IContentCardProps) => {
const { user } = useUser();
const [open, setOpen] = useState<boolean>(false);
return (
<Box
p={2}
height="300px"
maxWidth="250px"
display="flex"
flexDirection="column"
justifyContent="space-between"
border={`1px solid ${blue.main}`}
sx={{
cursor: "pointer",
":hover": { boxShadow: `0px 0px 3px 1px ${blue.main}` },
}}
onClick={() => setOpen(true)}
>
<Typography
variant="body1"
gutterBottom
fontWeight={700}
color={blue.main}
>
{content?.title}
</Typography>
<Typography
variant="caption"
marginBottom={1}
lineHeight={1.6}
textOverflow="ellipsis"
display="-webkit-box "
overflow="hidden"
sx={{ WebkitLineClamp: 8, WebkitBoxOrient: "vertical" }}
>
{content?.description}
</Typography>
<Box pt={1} display="flex" alignItems="center" borderTop={`1px solid ${grey.extraLight}`}>
<SvgIcon component={AccessTimeOutlinedIcon} sx={{ mr: 1 }} />
<Typography variant="caption" fontWeight={700}>
<span>{content?.duration}</span> min
</Typography>
</Box>
<ContentDialog open={open} setOpen={setOpen} />
</Box>
);
};
export default ContentCard;
The dialog component :
const Transition = forwardRef(function Transition(
props: TransitionProps & {
children: React.ReactElement;
},
ref: React.Ref<unknown>,
) {
return <Slide direction="left" ref={ref} {...props} />;
});
interface IContentDialogProps {
open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
}
const ContentDialog = ({ open, setOpen }: IContentDialogProps) => {
return (
<>
<Dialog fullScreen open={open} onClose={() => setOpen(false)} TransitionComponent={Transition}>
<AppBar sx={{ position: "relative", backgroundColor: blue.main }}>
<Toolbar>
<IconButton edge="start" color="inherit" onClick={() => setOpen(false)} aria-label="close">
<CloseIcon />
</IconButton>
</Toolbar>
</AppBar>
<Box> content</Box>
</Dialog>
</>
);
};
SetOpen does not seem to work on the Dialog and I don't know why... <br />
If anyone has an idea that would be great ! <br />
答案1 {#1}
得分: 0
点击关闭按钮会触发点击事件,该事件也可能会冒泡并意外地触发父元素上的点击事件。这会导致在 ContentCard
中的 <Box>
元素上执行 onClick={() => setOpen(true)}
函数。为了防止这种情况发生,您可以在关闭按钮的点击事件上使用 stopPropagation
。如下所示:
onClick={(e) => {
e.stopPropagation();
setOpen(false);
}}
此外,因为您主要是在 ContentDialog
中关闭对话框,您可以在 ContentCard
中创建该函数。然后,您可以传递该函数而不是 setState
函数。
如果您不想使用 stopPropagation
,您可以简单地将 ContentDialog
放在 Box
元素之外。这样,对话框将不再是盒子元素的直接子元素。如下所示:
function ContentCard({ content }) {
const [open, setOpen] = useState(false);
const onClose = (e) => setOpen(false);
return (
<>
<Box></Box>
<ContentDialog open={open} onClose={onClose} />
</>
);
}
英文:
Clicking the close button triggers a click event, which can also bubble up and inadvertently trigger a click event on the parent element. This results in the execution of the onClick={() => setOpen(true)}
function on the <Box> element within ContentCard
. To prevent this, you can use stopPropagation
on the close button's click event. Here's how:
onClick={(e) => {
e.stopPropagation();
setOpen(false);
}}
Additionally, because you're mainly closing the dialog in ContentDialog
, you can create that function in ContentCard
. Then, you can pass that instead of setState
function.
If you prefer not to use stopPropagation
, you can simply place the ContentDialog
outside the Box
element. This way, the dialog won't be a direct child of the box element anymore. Here's how you can do it:
function ContentCard({ content }) {
const [open, setOpen] = useState(false);
const onClose = (e) => setOpen(false);
return (
<>
<Box></Box>
<ContentDialog open={open} onClose={onClose} />
</>
);
}