Как стать автором
Обновить

Комментарии 18

Это джун писал?

Всё начинает идти не так с описания шага 1. ModalNames у нас какого-то лешего с большой буквы, хотя это не тип, и даже не енум, и уж тем более не класс.

"Строгая типизация обеспечивает дополнительную уверенность и удобство" - нет, она не работает в рантайме. Тайпскрипт никак не запретит вызвать второе окно когда открыто первое.

Ключи в объекте, задаваемые через манипуляцию со строками, и функция capitalizeFirstLetter - это что вообще за нафиг??

По функционалу - конечно же эта приблуда не дружит с анимациями исчезновения, это можно заметить даже визуально когда пропадает попап с данными (остаются названия полей, а значений нет) и layout shift может быть гораздо больше если там картинка какая или большой текст. А если в одном попапе юзер нажмёт условное "да", а скажем средств не хватает и юзеру нужно показать ошибку? Где закрытие одного (ждем анимацию) и только потом открытие следующего?

И вишенка на торте - это ни разу не модалка а попап. А бизнесу может быть надо функционал именно модалки, что её не закроешь пока допустим юзер не тыкнет "да согласен".

И вишенка на торте - это ни разу не модалка а попап.

В статье показал как работаю с открытием и закрытием Модальных окон, конкретно в примере испльзуется Dialog из Material UI, вот выжимка из документации:

A Dialog is a type of modal window that appears in front of app content to provide critical information or ask for a decision. 

По функционалу - ....,

Все, что вы описали можно легко реализовать при помощи этого великолепного инструмента, я показал основной функционал.

 что её не закроешь пока допустим юзер не тыкнет "да согласен".

Возможно, когда будет больше времени, специально напишу статью, о том как добавить кнопку "да согласен" в модальное окно и повесить на нее обработчик. Не думал, что это вызывает трудность в понимании.

Прежде чем в меня кидаться докой из ui библиотеки, можно почитать доку родного html диалога и в чем там разница между модальным и немодальным диалогом, чтобы не мешать тёплое с мягким.

Ну а по поводу анимации - это не опять же не придирка. Одна из главных проблем модалок/попапов - когда их может быть не одна, нужно грамотно ждать пока закроется одно прежде чем открывать другое. Хранить состояние диалогового окна в ячейке стора, как это показано в примере статьи - тут много ума не надо, это может сделать любой за 5 минут

Очень много кода ради очень примитивного функционала. Например, непонятно, как можно в эту модалку всунуть, к примеру, форму, которая будет что-то делать с продуктом из таблицы, а потом автоматически закрываться и обновлять строку таблицы.

Также из такой модалки не получится открыть дочернюю модалку, а это достаточно распространённый кейс.

Например, непонятно, как можно в эту модалку всунуть, к примеру, форму ...

В модалку можно всунуть что угодно, вот очередная форма в модальном окне в моей работе

Также из такой модалки не получится открыть дочернюю модалку, 

В нашей команде это плохой подход - модалка в модалке, но в любом случае статья показывает подход, если не подходит под ваши задачи, то жаль конечно

Очень много кода ради очень примитивного функционала

Если поделитесь своим решением этой проблемы, буду признателен, желательно так же подробно как я в статье

Если поделитесь своим решением этой проблемы

Не надо ничего изобретать. Есть библиотека react-modal, которая отлично работает. Также модалки отлично реализованы в Material UI, Ant Design, reactstrap и т.д. Когда модалка - это компонент, то это значительно удобнее, чем хуки. Кстати говоря, в соседнем комментарии на Vue предлагают именно компонентный подход.

модалки отлично реализованы в Material UI, Ant Design, reactstrap и т.д. Когда модалка - это компонент, то это значительно удобнее, чем хуки


Я испльзую Material UI, но удобного способа закрывать и открывать + передавать данные в модальные окна я не нашел и придумал свой, которым поделился.

Статья не о создании модального окна, а об управлении сосотянием модальных окон при помощи хука.

Если будет, что дополнить по существу, то пишите, с удовольствием вникну в ваше предложение, а просто перечислять название UI библиотек не имеет смысла.

Пишу на Vue.js, но думаю, что это применимо и к реакту: избежать хаоса можно создав компонент, который содержит компонент для диалога, у которого если есть слот, то при нажатии на него открывается этот диалог либо же если его нет, то диалог открывается автоматически.

Сильно упрощённый пример:

<SomeCustomDialog v-slot="{ onShow }">
  <Button @click="onShow" />
</SomeCustomDialog>

SomeCustomDialog.vue

<div class="some_dialog_wrapper">
   <slot :onShow="showDialog" />
   <Dialog
     v-if="dialogActive"
     v-model="dialogActive"
   >
     Dialog Content
   </Dialog>
</div>

Спасибо, что поделились своим подходом.

А как вы передаете данные в вашем подходе?
Например из таблицы, как в моем примере?

Практически всегда это обычные события, в прям очень редких исключениях использую хранилище

<SomeCustomDialog ... @someData="onSomeCustomDialogData($event)">

Внутри компонента опять же практически всегда событие вызываю на закрытие диалога:

<Dialog ... @onClose="emit('someData', someData)">

Отвечу за свои проекты. Тоже на Vue пишу в основном, модалки используем самописные, через portal(vue2) или teleport(vue3) для глобализации. Конкретно пример с модалками "форма записи в таблице", - в слотах передаем компоненты, которые уже содержат нужные пропсы типизированные, например "id продукта", сама форма уже работает с сервисом для загрузки и сохранения. Т.е. подход для форм немного другой, всё по тому, что от бизнеса была задача сделать "выбор" - открываем в модалке или новом окне, и очевидно компонент переиспользется во вьюхе и пропсы идут из компонента обертки в роутере. Поэтому у нас модалки это просто вариант отрисовки, не более. Ну и реально довольном частый кейс это модалка в модалке, например в форме "продукт" поле-лукап содержащий сложный грид с фильтрацией и прочем, и в этот гридьмолно добавить новую запись прямо из грида через форму, итого уже 3 модалки. Пока не было проблем с логикой и перекрытием отрисовки т.к. работает простой принцип first on first out.

 в слотах передаем компоненты ...

Спасибо за ваш пример подхода.
Я пишу на React и не знаю такого понятия как слот.

 Ну и реально довольном частый кейс это модалка в модалке

У нас так не принято, но в любом случае при желании можно доработать мое решение и под такую задачу.

Я пишу на React и не знаю такого понятия как слот.

Самая близкая аналогия slot в react это props.children. Подход в коде другой, но смысл один и тот же: передача вложенного контента в компоненты.

Я не силён в реакте, вот примерная реализация моего кода выше

const ParentComponent = () => {
  return (
    <SomeCustomDialog
      render={({ onShow }) => (
        <button onClick={onShow}>Show Dialog</button>
      )}
    />
  );
}
const SomeCustomDialog = ({ children }) => {
  const [dialogActive, setDialogActive] = useState(false);

  const onShow = () => setDialogActive(true);
  const onHide = () => setDialogActive(false);

  return (
    <div className="some_dialog_wrapper">
      {children({ onShow })}
      {dialogActive && (
        <Dialog isOpen={dialogActive} onClose={onHide}>
          Dialog Content
        </Dialog>
      )}
    </div>
  );
};

Как применить этот подход к таблице?

В моей реализации я при мапинге рядов таблицы вешаю обработчик на каждый клик по каждому ряду

Само модальное окно находится в родительском компоненте, ну или даже если бы оно находилось бы здесь, то мне нужно в таком случае обернуть в модалку каждый ряд таблицы ?

Вот таким образом работает ваш подход в React, благодарю за ваш вариант, тоже можно рассмотреть как подход.

например "id продукта", сама форма уже работает с сервисом для загрузки и сохранения.

Именно так и делаю в основном, т.е при нажатии на строку таблицы я отправляю в стор ключ нужного мне модального окна и к примеру productId. Внтури модального окна компонент, который получает этот productId из хука и выполняет нужные действия: запрашивает продукт, формирует дефолтные данные для формы, обрабатывает занчения формы и т.д

В стате, я показал как с этим можно работать на простых примерах, но основную идею думаю донес, как применять решать уже читателям)

Благодарю за внимание!

Тоже делал свою утилитку как то для управления модальными окнами - https://www.npmjs.com/package/react-modaly

С тех пор ее и использую. Данные передаю напрямую в компонент, который обернут модальным окном.

Да посмотрел ваше решение, до публикации статьи хук который я испльзую назывался useDialogControl, т.к пользуюсь Dialog из Material UI, но т.к статья про модальные окна решил назвать useModalControl)

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории