Предупреждение: реакция-модальный: элемент приложения не определен. Пожалуйста, используйте `Modal.setAppElement (el)` или установите `appElement = {el}`

Как исправить это предупреждение в консоли приложения React с помощью пакета react-modal:

Предупреждение: реактивно-модальный: элемент приложения не определен. Используйте Modal.setAppElement(el) или установите appElement={el}

Мне не удалось выяснить, что же такое el.

Контекст: в моем файле корневого компонента App.js:

...
import Modal from 'react-modal';
...
class App extends Component {
  ...
  render(){
    ...  
    <Modal
      className="modal"
      overlayClassName="overlay"
      isOpen={foodModalOpen}
      onRequestClose={this.closeFoodModal}
      contentLabel="Modal"
    >
    ...
  }
}

Где ... означает, что код не показан.

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

index.js: 2177 Предупреждение: react-modal: элемент приложения не определен. Используйте Modal.setAppElement(el) или установите appElement={el}. Это необходимо, чтобы программы чтения с экрана не видели основной контент при открытии модального окна. Это не рекомендуется, но вы можете отказаться, установив ariaHideApp={false}.

Все, что я могу найти в модальных документах, это следующее:

Элемент приложения Элемент приложения позволяет вам указать часть вашего приложения, которая должна быть скрыта (с помощью aria-hidden), чтобы вспомогательные технологии, такие как программы чтения с экрана, не читали контент за пределами вашего модального окна.

Если вы выполняете рендеринг на стороне сервера, вам следует использовать это свойство.

Его можно указать следующими способами:

DOMElement
Modal.setAppElement(appElement);
query selector - uses the first element found if you pass in a class.
Modal.setAppElement('#your-app-element');

К сожалению, это не помогло! Я не могу понять, что должен представлять el.

Вот некоторые из множества вариантов свойств, которые я пытался добавить в свой модальный компонент:

`appElement={el}`,  
`appElement="root"` where `root` is the id that my App component is injected into   
`appElement={'root'}`   
`appElement="div"`,   
`appElement={<div>}`,   
`appElement={"div"}`  

Я также пробовал вызывать Modal.setAppElement('root'); изнутри src/index.js, где root - корневой элемент, в который вводится мой App компонент, а index.js - это то место, где я это делаю.


person SherylHohman    schedule 15.01.2018    source источник
comment
Ответ Шерил правильный, но, чтобы вы знали, el обычно относится к ссылке и является сокращением от элемента.   -  person famouspotatoes    schedule 27.04.2020


Ответы (11)


Добавьте ariaHideApp={false} к Modal атрибутам.

Это должно работать:

<Modal isOpen={!!props.selectedOption}
    onRequestClose={props.clearSelectedOption}
    ariaHideApp={false}
    contentLabel="Selected Option"
    >
</Modal>
person amrit chhetri    schedule 31.05.2018
comment
Из официальной документации: это не рекомендуется, но вы можете отказаться, установив ariaHideApp={false}. - person Frederiko Cesar; 22.06.2020

Некоторые решения приведены в вопросе реактивного модального окна № 133:

Проблема заключается в следующем: В зависимости от того, когда он оценивает реагирующий модальный @ 1.6.5: /lib/helpers/ariaAppHider.js#L1:

  • document.body еще не существует, и он будет преобразован в undefined || null.
  • если Modal.setAppElement() вызывается с null или не вызывается вообще с <script />, помещенным на <head /> (то же, что и выше).
  • Вероятно, это также может произойти, если вызвать selector, который не соответствует ни одному результату.

Решения:

Отрисовка в браузере:

фрагмент @yachaka предотвращает такое поведение, определяя элемент перед размещением <Modal />:

componentWillMount() {
    Modal.setAppElement('body');
}

@ungoldman answer, если вы не хотите зависеть от `setAppElement ':

Вставьте JS связанного приложения в <body> вместо <head>.
Хотя в идеале react-modal следует дождаться загрузки DOM, чтобы попытаться подключиться к document.body.

на стороне сервера:

При рендеринге на стороне сервера вы должны предоставить document.body, прежде чем требовать модальный сценарий (возможно, в этом случае предпочтительнее использовать setAppElement()).


Обновление: были созданы ответы на документы обновлен, чтобы включить приведенную выше информацию, поэтому теперь они должны быть более понятными для пользователей, столкнувшихся с этой проблемой.
реакция-модальная проблема № 567: добавьте информацию (из проблемы № 133, указанной выше) в документы.

person SherylHohman    schedule 15.01.2018
comment
если модальное окно используется только в компоненте, можно ли его смонтировать так, чтобы наложение перекрывало только этот компонент, а не родительских / прародителей этого компонента? Я попробовал, похоже, не сработало, снова закрывал весь экран. - person joedotnot; 31.10.2018
comment
Было бы полезно иметь новое решение сейчас, когда componentWillMount () устарел. Я не мог найти ни одного. - person Jamie McLaughlin; 05.04.2020

Просто включите appElement={document.getElementById('app')} внутри вашего модального окна, как это

<Modal
className="modal"
appElement={document.getElementById('app')}
>

Он будет работать на 100%, если приложение будет вашим центральным в index.html, откуда загружается реакция.

person Aditya Mishra    schedule 02.09.2018
comment
Вам может потребоваться резервный вариант для обеспечения безопасности типов, поскольку getElementById допускает значение NULL. - person Mo Beigi; 02.01.2021
comment
@MoBeigi appElement={document.getElementById('root') || undefined} кажется достаточно - person runeks; 27.05.2021

Это мой компонент TypeScript Modal, который является оболочкой react-modal v3.8.1:

import React from 'react'
import ReactModal from 'react-modal'

interface Props {
  isOpen: boolean
  ariaLabel?: string
}

const Modal: React.FC<Props> = ({
  children,
  ariaLabel = 'Alert Modal',
  isOpen,
}) => (
  <ReactModal
    appElement={document.getElementById('root') as HTMLElement}
    ariaHideApp={process.env.NODE_ENV !== 'test'}
    isOpen={isOpen}
    contentLabel={ariaLabel}
    testId="modal-content"
  >
    {children}
  </ReactModal>
)

export default Modal

Использование в компоненте с state = { isOpen: true }:

<Modal isOpen={this.state.isOpen}>
  <p>
    Modal Content here…
  </p>
  <button onClick={() => { this.setState({ isOpen: false }) }}>Okay</button>
</Modal>
person Beau Smith    schedule 13.02.2019
comment
Он также работает в проекте React TypeScript. - person Goran_Ilic_Ilke; 19.08.2020

Если вы получаете ошибку Warning: react-modal: App element is not defined... при запуске тестов (мы использовали Jest), вы можете подавить предупреждения, добавив в свой тестовый файл следующее:

import ReactModal from 'react-modal';
ReactModal.setAppElement('*'); // suppresses modal-related test warnings.
person JoeTidee    schedule 25.03.2019

Самым коротким решением является добавление appElement={document.getElementById("hereIsYourRootElementId")}. Он позволяет react-modal знать, где находится ваш корневой элемент. Это не обязательно, но рекомендуется.

person Marat Hakobjanyan    schedule 04.11.2019

Для справки, поскольку мне было больно, если вы работаете с SSR, используйте следующий код для предотвращения ошибок на стороне сервера:

if (typeof(window) !== 'undefined') {
    ReactModal.setAppElement('body')
}

Вы можете поместить это componentDidMount() везде, где вы используете модальное окно, или я поместил его в пользовательский модальный компонент, чтобы он был красивым и СУХИМ.

person Nathaniel Hill    schedule 22.04.2018
comment
react-modal был исправлен в апстриме, так что это больше не должно быть проблемой. - person Nathaniel Hill; 18.08.2018
comment
Это не так, я обновил модуль, но все равно получаю это предупреждение. - person JS dev; 27.08.2018

просто поместите этот Modal.setAppElement ('# root'). это устранит предупреждение. корневой элемент из общей папки index.html.

person karthickkannan    schedule 31.10.2020

вам нужно добавить # перед идентификатором корневого элемента.

import React from 'react';
import Modal from 'react-modal';


Modal.setAppElement('#root');

const OptionModal = (props) => (
  <Modal
    isOpen={!!props.selectedOption}
    contentLabel='this is the selected option'
  >
    <h3>Selected Option</h3>
    {props.selectedOption && <p>{props.selectedOption}</p>}
    <button onClick = {props.handleCloseOptionModal}>Close</button>
  </Modal>
);

export default OptionModal;

вот ссылка: http://reactcommunity.org/react-modal/accessibility/

person Mo Hemati    schedule 02.10.2018

Если вы получили это предупреждение при тестировании с помощью «react-testing-library», вот решение: https://github.com/reactjs/react-modal/issues/576#issuecomment-524644035

используя библиотеку response-testing (https://testing-library.com/), я избавляюсь от это предупреждение с:

import Modal from "react-modal";

const { container } = render(<MyComponent />);
Modal.setAppElement(container);

....  // to the testing, use Modal

или, если вы хотите напрямую протестировать модальный компонент:

const { container, rerender } render(<MyModalComponent isOpen={false} />);
Modal.setAppElement(container);
// now the appElement is set we can show the modal component
rerender(<MyModalComponent isOpen={false} />);

....  // to the testing
person Reinhard    schedule 25.08.2019

Удалите этот атрибут className = modal и запустите снова

person Tareik Netro    schedule 13.11.2020