如何在React中关闭自定义DialogueWindow对话框?
问题描述
我实现了一个通用的DialogueWindow组件,代码如下:
function DialogueWindow({elements}) { return ( <div className="backdrop"> <dialog className="dialogue-window"> {elements} </dialog> </div> ) } export default DialogueWindow
该组件会渲染传入的任意元素,当前我传入了带有取消按钮的FileUploader组件,用于关闭对话框。
在App.js中的使用方式:
<DialogueWindow elements={ <FileUploader/> } />
FileUploader组件代码:
function FileUploader() { ... return ( <div className="file-uploader"> ... <div className="file-uploader-button-container"> <button> Upload </button> <button> Cancel </button> </div> </div> ) } export default FileUploader
我知道在原生JavaScript中可以通过document.getElementById()获取dialog元素并调用close()方法关闭,但不清楚在React中该如何实现?
解决方案
在React中不推荐直接操作DOM,更符合React数据流的方式有两种,具体实现如下:
方式一:使用Ref调用dialog原生close方法
通过React的useRef获取dialog元素,再把关闭函数传递给子组件:
- 修改DialogueWindow组件,添加ref和关闭方法:
import { useRef } from 'react'; function DialogueWindow({elements}) { const dialogRef = useRef(null); const closeDialog = () => { dialogRef.current?.close(); }; // 克隆传入的元素并注入关闭函数 const elementsWithCloseProp = React.cloneElement(elements, { closeDialog }); return ( <div className="backdrop"> <dialog ref={dialogRef} className="dialogue-window" open> {elementsWithCloseProp} </dialog> </div> ) } export default DialogueWindow
- 修改FileUploader组件,接收关闭函数并绑定到Cancel按钮:
function FileUploader({ closeDialog }) { ... return ( <div className="file-uploader"> ... <div className="file-uploader-button-container"> <button> Upload </button> <button onClick={closeDialog}> Cancel </button> </div> </div> ) } export default FileUploader
方式二:通过状态控制dialog的显示(更推荐)
用React状态管理对话框的显示/隐藏,完全遵循单向数据流:
- 在父组件(如App.js)中维护对话框状态,传递控制函数:
import { useState } from 'react'; import DialogueWindow from './DialogueWindow'; import FileUploader from './FileUploader'; function App() { const [isDialogOpen, setIsDialogOpen] = useState(true); const closeDialog = () => { setIsDialogOpen(false); }; return ( <div> {isDialogOpen && ( <DialogueWindow elements={<FileUploader closeDialog={closeDialog} />} /> )} </div> ) } export default App
- 保持DialogueWindow组件简洁,直接渲染传入元素:
function DialogueWindow({elements}) { return ( <div className="backdrop"> <dialog className="dialogue-window" open> {elements} </dialog> </div> ) } export default DialogueWindow
- 同样修改FileUploader组件绑定关闭函数:
function FileUploader({ closeDialog }) { ... return ( <div className="file-uploader"> ... <div className="file-uploader-button-container"> <button> Upload </button> <button onClick={closeDialog}> Cancel </button> </div> </div> ) } export default FileUploader
如果需要支持点击遮罩层关闭对话框,可以在DialogueWindow中添加事件监听:
function DialogueWindow({elements, onClose}) { const handleBackdropClick = (e) => { if (e.target.classList.contains('backdrop')) { onClose(); } }; return ( <div className="backdrop" onClick={handleBackdropClick}> <dialog className="dialogue-window" open> {elements} </dialog> </div> ) }
然后在App.js中传递onClose={closeDialog}给DialogueWindow即可。
内容的提问来源于stack exchange,提问作者user30266210
相关产品推荐
相关产品推荐

