“警告:react-modal:App 元素未定义。请使用 `Modal.setAppElement(el)` 或设置 `appElement=el`”

Posted

技术标签:

【中文标题】“警告:react-modal:App 元素未定义。请使用 `Modal.setAppElement(el)` 或设置 `appElement=el`”【英文标题】:"Warning: react-modal: App element is not defined. Please use `Modal.setAppElement(el)` or set `appElement=el`"“警告:react-modal:App 元素未定义。请使用 `Modal.setAppElement(el)` 或设置 `appElement=el`” 【发布时间】:2018-06-24 11:04:11 【问题描述】:

如何使用 react-modal 包在 React 应用程序的控制台中修复此警​​告:

警告:react-modal:App 元素未定义。请使用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"
    >
    ...
  

... 表示代码未显示。

一切正常,但是当打开 Modal 时,我的控制台中会出现以下警告:

index.js:2177 警告:react-modal:App 元素未定义。请使用Modal.setAppElement(el) 或设置appElement=el。这是必需的,以便屏幕阅读器在打开模式时看不到主要内容。不推荐,但您可以通过设置ariaHideApp=false 选择退出。

在react-modal docs 中,我只能找到以下内容:

应用元素 app 元素允许您指定应隐藏的应用程序部分(通过 aria-hidden),以防止屏幕阅读器等辅助技术读取模态内容之外的内容。

如果你在做服务器端渲染,你应该使用这个属性。

可以通过以下方式指定:

DOMElementModal.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"`  

我还尝试从src/index.js 内部调用Modal.setAppElement('root');,其中root 是我的App 组件注入的根元素,而index.js 就是我这样做的地方。

【问题讨论】:

Sheryl 的回答是正确的——但请注意,“el”通常指的是 ref,是“element”的缩写。 【参考方案1】:

ariaHideApp=false 添加到Modal 属性。

这应该有效:

<Modal isOpen=!!props.selectedOption
    onRequestClose=props.clearSelectedOption
    ariaHideApp=false
    contentLabel="Selected Option"
    >
</Modal>

【讨论】:

来自官方文档:不推荐,但可以设置ariaHideApp=false退出。【参考方案2】:

部分解决方案在react-modal issue #133:中给出

The problem lies here: 取决于它何时评估 react-modal@1.6.5:/lib/helpers/ariaAppHider.js#L1:

document.body 还不存在,它将解析为undefined || null。 如果Modal.setAppElement() 是用null 调用的,或者根本不调用&lt;script /&gt; 放在&lt;head /&gt; 上(同上)。 如果使用不匹配任何结果的selector 调用,也可能会发生这种情况。

解决方案:

浏览器渲染:

@yachaka snippet 通过在放置&lt;Modal /&gt; 之前定义元素来防止这种行为:

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

@ungoldman answer,如果你不想依赖`setAppElement':

将捆绑的应用程序JS注入&lt;body&gt;而不是&lt;head&gt;。 虽然理想情况下react-modal 应该等到 DOM 加载后尝试附加到document.body

服务器端:

如果在服务器端呈现,您必须在需要模态脚本之前提供document.body(在这种情况下,最好使用setAppElement())。


更新: react docs 已更新以包含上述信息,因此对于遇到此问题的用户来说,它们现在应该更清楚了。react-modal issue #567: 将信息(来自上面链接的问题 #133)添加到文档中。

【讨论】:

如果模态仅在组件中使用,是否可以安装它以使覆盖层仅覆盖该组件 - 而不是该组件的父/祖父母?我试了一下,好像不行,又回到了全屏。 由于 componentWillMount() 已被弃用,因此有一个新的解决方案会很有用。我找不到。【参考方案3】:

像这样在你的模态中包含appElement=document.getElementById('app')

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

如果应用程序是您在 index.html 中加载反应的中心,它将 100% 工作。

【讨论】:

由于getElementById 可以为空,您可能需要回退以确保类型安全。 @MoBeigi appElement=document.getElementById('root') || undefined 似乎就够了【参考方案4】:

这是我的 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>

【讨论】:

它也适用于 react typescript 项目。所以,赞成。【参考方案5】:

如果在运行测试(我们正在运行 Jest)时收到 Warning: react-modal: App element is not defined... 错误,您可以通过将以下内容添加到您的测试文件来抑制警告:

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

【讨论】:

【参考方案6】:

最短的解决方案是添加appElement=document.getElementById("hereIsYourRootElementId")

它让 react-modal 知道你的根元素在哪里。

【讨论】:

【参考方案7】:

就放这个Modal.setAppElement('#root')

这将解决警告。来自公用文件夹 index.html 内部的根元素。

【讨论】:

【参考方案8】:

作为参考,因为这对我来说很痛苦,如果你正在做 s-s-r,请使用以下代码来防止服务器端错误:

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

你可以把它放在componentDidMount() 任何你使用模态的地方,或者我把它放在一个自定义的模态组件中,这样它既好又干。

【讨论】:

react-modal 已在上游修复,所以这应该不再是问题了。 不是,我更新了模块但仍然收到此警告。【参考方案9】:

您需要在根元素 ID 之前添加 #。

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/

【讨论】:

【参考方案10】:

如果您在使用“react-testing-library”进行测试时收到警告,这里有一个解决方案: https://github.com/reactjs/react-modal/issues/576#issuecomment-524644035

使用 react-testing-library (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

【讨论】:

【参考方案11】:

删除此属性 类名=“模态” 然后再次运行

【讨论】:

以上是关于“警告:react-modal:App 元素未定义。请使用 `Modal.setAppElement(el)` 或设置 `appElement=el`”的主要内容,如果未能解决你的问题,请参考以下文章