如何使用反应模态包在 React 应用程序的控制台中修复此警告:
警告:反应模式:未定义应用程序元素。请使用
Modal.setAppElement(el)
或设置appElement={el}
我还没有成功地弄清楚el
应该是什么。
上下文: 在我的应用程序中.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 警告:反应模式:未定义应用元素。请使用
Modal.setAppElement(el)
或设置appElement={el}
。这是必需的,以便屏幕阅读器在打开模式时看不到主要内容。不建议这样做,但您可以通过设置ariaHideApp={false}
来选择退出。
在反应模态文档中,我能找到的只有以下内容:
应用元素 app 元素允许您指定应隐藏的应用部分(通过 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"}`
我还尝试从src/index.js
内部调用Modal.setAppElement('root');
,其中root
是我的App
组件注入到的根元素,而 index.js 是我这样做的地方。
将ariaHideApp={false}
添加到Modal
属性。
这应该有效:
<Modal isOpen={!!props.selectedOption}
onRequestClose={props.clearSelectedOption}
ariaHideApp={false}
contentLabel="Selected Option"
>
</Modal>
反应模态问题 #133 中给出了一些解决方案:
问题就在这里: 根据它何时计算 react-modal@1.6.5:/lib/helpers/ariaAppHider.js#L1:
- document.body 尚不存在,它将解析为
undefined || null
。 - 如果使用
null
调用Modal.setAppElement()
,或者根本不调用放置在<head />
上的<script />
(与上述相同)。 - 如果使用与任何结果都不匹配的
selector
调用,也可能发生这种情况。
解决 方案:
浏览器渲染:
@yachaka代码段通过在放置<Modal />
之前定义元素来防止此行为:
componentWillMount() {
Modal.setAppElement('body');
}
@ungoldman答案,如果你不想依赖'setAppElement':
将捆绑的应用程序 JS 注入
<body>
而不是<head>
。
尽管理想情况下react-modal
应该等到 DOM 加载后再尝试附加到document.body
.
服务器端:
如果在服务器端渲染,则必须在需要模态脚本之前提供一个
document.body
(在这种情况下,也许最好使用setAppElement()
)。
更新: React 文档已更新以包含上述信息,因此对于遇到此问题的用户来说,它们现在应该更清晰。
反应模式问题 #567:将信息(来自上面链接的问题 #133)添加到文档中。
只需像这样将appElement={document.getElementById('app')}
包含在您的模态中
<Modal
className="modal"
appElement={document.getElementById('app')}
>
如果应用程序是索引的中心.html则它将 100% 工作,从 react 加载的位置。
这是我的TypeScriptModal
组件,它包装了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>
如果在运行测试时收到Warning: react-modal: App element is not defined...
错误(我们正在运行 Jest),您可以通过向测试文件添加以下内容来禁止显示警告:
import ReactModal from 'react-modal';
ReactModal.setAppElement('*'); // suppresses modal-related test warnings.
只需输入这个Modal.setAppElement('#root')
这将解决警告。来自公用文件夹索引.html内部的根元素。
最短的解决方案是添加appElement={document.getElementById("hereIsYourRootElementId")}
它让反应模态知道你的根元素在哪里。
作为参考,由于这对我来说很痛苦,如果您正在执行 SSR,请使用以下代码来防止服务器端出现错误:
if (typeof(window) !== 'undefined') {
ReactModal.setAppElement('body')
}
你可以把它放在任何使用模态的地方componentDidMount()
或者我把它放在一个自定义的模态组件中,所以它很好而且很干。
您需要在根元素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/
对于 Nextjs,我认为您可以通过在声明组件之前将以下内容添加到模态组件外部(可能在顶部)来解决此问题。
Modal.setAppElement('#__next')
如果您在使用"react-testing-library"进行测试时收到警告,这里有一个解决方案: https://github.com/reactjs/react-modal/issues/576#issuecomment-524644035
使用反应测试库(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
在 nextjs 中解决:这为我解决了,我只是在布局中的根主体中添加了一个 id,然后在模态中添加了一个appElement={document.getElementById("root")}
。
布局.js组件
<body suppressHydrationWarning={true} id='root'>
<div className='main-container col-12 d-flex flex-row h-100 w-100 col-12 justify-content-start align-items-start'>
<main className='col-10'>{children}</main>
</div>
</body>
一些组件
<Modal
isOpen={modalIsOpen}
onRequestClose={closeModal}
contentLabel='Book Modal'
appElement={document.getElementById("root")}
style={{
content: {
width: "850px",
height: "85vh",
margin: "auto",
padding: "0px",
border: "none",
overflow: "hidden",
},
}}
>
<h1>Content Of Modal Goes Here</h1>
</Modal>
删除此属性 类名称="模态" 并再次运行