Закрытие диалогового окна пользовательского интерфейса материала из дочернего компонента инициирует открытие диалогового окна родителя

#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. Моя цель состоит в том, чтобы предотвратить открытие родительского диалога, когда ребенок закрыт.