#reactjs #material-ui
Вопрос:
У меня есть 2 диалога, один во внешней области (родительский) и один в качестве дочернего.
export default function App() {
const [parentDialogOpen, setParentDialogOpen] = useState(false);
const [childDialogOpen, setChildDialogOpen] = useState(false);
const handleParentClick = () => {
setParentDialogOpen(true);
};
const handleChildClick = (e) => {
e.stopPropagation();
setChildDialogOpen(true);
};
return (
<div className="App">
<Dialog
open={parentDialogOpen}
onClose={() => setParentDialogOpen(false)}
>
<Box p={4}>Parent Dialog</Box>
</Dialog>
<Box bgcolor="red" p={2} onClick={handleParentClick}>
<Dialog
open={childDialogOpen}
onClose={(e) => setChildDialogOpen(false)}
>
<Box p={2}>Child Dialog</Box>
</Dialog>
<button onClick={handleChildClick}>Child</button>
</Box>
</div>
);
}
Когда я нажимаю на кнопку, открывается диалоговое окно (Дочернее диалоговое окно), но когда я закрываю его, появляется Родительское диалоговое окно. Мое ожидаемое поведение заключается в том, что нажатие на дочернюю кнопку не должно вызывать onClick
событие у родителя (как я добавил e.stopPropagation()
в onClick
обработчик ребенка).
Добавление e.stopPropagation()
handleChildClick
останавливает распространение события на Родительское onClick
, но когда я закрываю диалоговое окно, Родительское все onClick
еще срабатывает.
Я также попытался добавить e.stopPropagation()
в Дочерний диалог onClose
, но это не помогает.
Хотя перемещение дочернего диалогового окна на тот же уровень, что и Родительское диалоговое окно, заставляет его работать должным образом, я не могу этого сделать, потому что в моем (реальном) коде я должен динамически отображать дочерний компонент, который у дочернего компонента может быть свой собственный диалог.
Есть ли способ решить эту проблему?
[ОБНОВЛЕНИЕ]: Похоже onClick
, что событие родительского диалога также срабатывает при нажатии в ЛЮБОМ МЕСТЕ, когда открыт дочерний диалог. Например, щелчок ВНУТРИ дочернего диалога приведет к запуску родительского диалога onClick
(без закрытия дочернего диалога).
Вот Кодовая песочница: https://codesandbox.io/embed/eloquent-hypatia-nuksu?размер шрифта=14 и скрытая навигация=1 и тема=темная
Комментарии:
1.
handleParentClick
не привязан к родительскому диалогу, он привязан к родительскому div дочернего диалога. Это естественное поведение, которое запускается, когда вы нажимаете в любом месте детского диалога
Ответ №1:
Просто остановите распространение в событии onClick диалогового окна (см. Ниже).
import "./styles.css";
import { Box, Dialog } from "@material-ui/core";
import { useState } from "react";
export default function App() {
const [parentDialogOpen, setParentDialogOpen] = useState(false);
const [childDialogOpen, setChildDialogOpen] = useState(false);
const handleParentClick = () => {
setParentDialogOpen(true);
};
const handleChildClick = (e) => {
e.stopPropagation();
setChildDialogOpen(true);
};
return (
<div className="App">
<Dialog
open={parentDialogOpen}
onClose={() => setParentDialogOpen(false)}
>
<Box p={4}>Parent Dialog</Box>
</Dialog>
<Box bgcolor="red" p={2} onClick={handleParentClick}>
<Dialog
open={childDialogOpen}
onClick={(e) => e.stopPropagation()}
onClose={(e) => setChildDialogOpen(false)}
>
<Box p={2}>Child Dialog</Box>
</Dialog>
<button onClick={handleChildClick}>Child</button>
</Box>
</div>
);
}
Комментарии:
1. Это действительно решает мою проблему. Однако существуют ли какие-либо другие решения, в которых мне не нужно добавлять это
onClick
событие в дочернее диалоговое окно? В противном случае каждый дочерний диалог (который можно использовать в другом месте) всегда должен добавлять это специальноеonClick
событие, а не лучший сценарий при работе с большим количеством компонентов и команды.2. Вы можете попробовать что-то подобное, если хотите избежать использования onClick : codesandbox.io/s/white-flower-0m1vp?file=/src/App.js
3. Перемещение дочернего диалогового окна из родительского контейнера для меня не является вариантом, так как оно будет отображаться динамически (как указано в вопросе). Тем не менее, я приму первое решение в качестве ответа, потому что это можно сделать, переопределив весь диалог material-ui через muiTheme.
Ответ №2:
если ваша цель состоит в том, чтобы открыть родительский диалог, когда ребенок закрыт, вы можете сделать следующее;
...
...
<Dialog
open={childDialogOpen}
onClose={(e) => {
setChildDialogOpen(false);
setParentDialogOpen(true);
}}
>
Тогда избавься от handleParentClick
этого навсегда
Комментарии:
1. Моя цель состоит в том, чтобы предотвратить открытие родительского диалога, когда ребенок закрыт.