У меня есть компонент React для модального диалога. Это прекрасно работает, когда я не делаю с ним ничего особенного:
return (
<Modal className={isShowing ? "modal is-active" : "modal"}>
<ModalBackground></ModalBackground>
<ModalCard>
<ModalHeader>
<ModalTitle>
<NoticeIcon type={noticeType}/>
{title}
</ModalTitle>
<ModalClose onClick={handleHideModal}></ModalClose>
</ModalHeader>
<ModalContent>
{content}
</ModalContent>
<ModalFoot>
{ buttonSpecs.map((spec) =>
<BottomButton key={spec.label} label={spec.label} handleClick={spec.handleClick} isPrimary={spec.isPrimary} />
)}
</ModalFoot>
</ModalCard>
</Modal>
);
Тем не менее, предписанный подход к отображению диалогового окна состоит в том, чтобы отображать его внизу документа DOM, а не вклинивать его внутри компонент вызывает его, в том числе тот, в который внешний элемент DOM компонента может даже не быть разрешен. (Действительно, в одном случае я вызываю модальное диалоговое окно из компонента, который отображает строку таблицы, в TR. Это «работает», но выдает сообщение об ошибке на консоль Chrome, как ничего, кроме TH и TD разрешены внутри ТР). Это можно сделать с помощью ReactDOM.createPortal
:
import ReactDOM from 'react-dom';
...
return (ReactDOM.createPortal(
<Modal className={isShowing ? "modal is-active" : "modal"}>
<ModalBackground></ModalBackground>
<ModalCard>
<ModalHeader>
<ModalTitle>
<NoticeIcon type={noticeType}/>
{title}
</ModalTitle>
<ModalClose onClick={handleHideModal}></ModalClose>
</ModalHeader>
<ModalContent>
{content}
</ModalContent>
<ModalFoot>
{ buttonSpecs.map((spec) =>
<BottomButton key={spec.label} label={spec.label} handleClick={spec.handleClick} isPrimary={spec.isPrimary} />
)}
</ModalFoot>
</ModalCard>
</Modal>
), document.body);
. Вызов ReactDOM.createPortal
со вторым параметром document.body
должен визуализировать компонент в конце тела. Но это выдает мне ошибку: «Целевой контейнер не является элементом DOM» .
В то время, когда я показываю диалог, страница и все остальное в нем уже существует, поэтому тело существует.
Я попробовал другой объясненный подход, который заключается в создании явного div в конце внешней HTML структуры документа в качестве контейнера для модального:
<div id="root"></div>
<div id="modalRoot"></div>
и затем замените document.getElementById('modalRoot')
на document.body
. Но это дает мне ту же ошибку.
Единственные ответы, которые я нашел для этого, включают случаи, когда модал вызывается при первом рендеринге скриптом, который находится в разделе HEAD документа, так что тело не существует Совет в тех случаях состоял в том, чтобы переместить сценарий в конец документа. В моем случае диалоговое окно отображается в ответ на некоторые мои действия внутри документа, который уже был обработан.
Есть идеи?