我有一个通用的 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() 来获取对话框元素,然后对其调用 close() 方法。但这在 React 中是如何实现的呢?
基本上,在 React 中,状态通常与需要控制渲染的组件绑定。所以在你的情况下,
DialogueWindow
就是控制部分。它并不能决定对话框是打开还是关闭,这可能是上游的(比如app
),这就是为什么你的方法不起作用。任何子组件 ( ) 都可以通过将回调函数作为 prop 向下
FileUploader
传递来告诉其父组件 (DialogueWindow
) 或祖父组件 (App
) 执行某些操作,例如关闭对话框。然后,当按钮被点击时,子组件就会调用此函数。如何修复:
添加一个状态变量
app
(或其他等效变量)。这将跟踪对话框是否打开。App
应该将状态和关闭对话框的函数传递给DialogueWindow
。DialogueWindow
需要将关闭函数传递给FileUploader
。FileUploader
的取消按钮需要调用上面的关闭函数。在App.js (或同等版本)中:您需要在应用中添加状态变量,并有条件地显示对话。
在DialougeWindow.js中:获取 onClose 属性并直接获取 DOM 的引用
<dialouge>
在FileUploader.js中:它现在接受来自其父级的 onClose 属性。
会发生什么:
在 中
App
,isDialogueOpen 为 false。DialogueWindow
未渲染。用户单击中的打开按钮
App
。调用App中的handleOpenDialogue,将isDialogueOpen设置为true。
React 重新渲染 App。由于 isDialogueOpen 为 true,
DialogueWindow
因此现在已渲染。App
将 handleCloseDialogue 作为 onClose 传递给DialogueWindow
并且也传递给FileUploader
内部DialogueWindow
的元素 prop。DialogueWindow
挂载。它的 useEffect 运行,调用 dialogRef.current.showModal(),这意味着原生对话框现在可见。然后,它添加了原生的 close 事件监听器,以便我们稍后进行修改。FileUploader 挂载在 内部
DialogueWindow
。它接收 handleCloseDialogue 作为其 onClose 属性。用户点击 FileUploader 中的“取消”按钮。
FileUploader 中的 handleCancelClick 被调用,执行 props.onClose()。
在App中调用handleCloseDialogue,将isDialogueOpen设置回false。
React 重新渲染 App。由于 isDialogueOpen 为 false,条件渲染 isDialogueOpen && (...) 也为 false,因此
DialogueWindow
该渲染从 DOM 中移除。卸载时
DialogueWindow
,React 会清理 useEffect,移除原生的 close 事件监听器。原生对话框元素也会从 DOM 中移除。有道理吗?
您可以在React Learn: 管理状态 和 React Learn: 逃生舱口中了解有关状态和道具的更多信息
典型的做法是添加一个状态变量来确定是否
<DialogueWindow />
渲染。状态变量将通过一个函数进行控制,该函数需要从父级传递到
Cancel
按钮所在的位置。您可能还需要
onClose
在成功上传后调用,以防止对话框永远显示。App.js:
FileUploader.js: