AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79596016
Accepted
user30266210
user30266210
Asked: 2025-04-28 16:06:42 +0800 CST2025-04-28 16:06:42 +0800 CST 2025-04-28 16:06:42 +0800 CST

如何在 React 中关闭对话框?

  • 772

我有一个通用的 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 中是如何实现的呢?

javascript
  • 2 2 个回答
  • 51 Views

2 个回答

  • Voted
  1. Ma7erial
    2025-04-28T16:54:02+08:002025-04-28T16:54:02+08:00

    基本上,在 React 中,状态通常与需要控制渲染的组件绑定。所以在你的情况下,DialogueWindow就是控制部分。它并不能决定对话框是打开还是关闭,这可能是上游的(比如app),这就是为什么你的方法不起作用。

    任何子组件 ( ) 都可以通过将回调函数作为 prop 向下FileUploader传递来告诉其父组件 ( DialogueWindow) 或祖父组件 ( App) 执行某些操作,例如关闭对话框。然后,当按钮被点击时,子组件就会调用此函数。

    如何修复:

    1. 添加一个状态变量app(或其他等效变量)。这将跟踪对话框是否打开。

    2. App应该将状态和关闭对话框的函数传递给DialogueWindow。

    3. DialogueWindow需要将关闭函数传递给FileUploader。

    4. FileUploader的取消按钮需要调用上面的关闭函数。

    在App.js (或同等版本)中:您需要在应用中添加状态变量,并有条件地显示对话。

    
    function App() {
      const [isDialogueOpen, setIsDialogueOpen] = useState(false);
    
      const handleOpenDialogue = () => {
        setIsDialogueOpen(true);
      };
    
      const handleCloseDialogue = () => {
        setIsDialogueOpen(false);
      };
    
      return (
        <div className="App">
          <h1>My App</h1>
          <button onClick={handleOpenDialogue}>Open File Uploader</button>
    
          {/* Conditionally render the DialogueWindow based on that state we put up top */}
          {isDialogueOpen && (
            <DialogueWindow
              // Pass the close handler down
              onClose={handleCloseDialogue}
              elements={
                // Pass the close handler down to the FileUploader too.
                <FileUploader onClose={handleCloseDialogue} />
              }
            />
          )}
        </div>
      );
    }
    
    export default App;
    
    

    在DialougeWindow.js中:获取 onClose 属性并直接获取 DOM 的引用<dialouge>

    import React, { useRef, useEffect } from 'react';
    import './DialogueWindow.css';
    
    function DialogueWindow({ elements, onClose }) {
      const dialogRef = useRef(null);
    
      useEffect(() => {
        const dialogElement = dialogRef.current;
    
        if (dialogElement) {
          dialogElement.showModal();
    
          const handleNativeClose = () => {
             if (onClose) {
               onClose();
             }
          };
          dialogElement.addEventListener('close', handleNativeClose);
    
          return () => {
            dialogElement.removeEventListener('close', handleNativeClose);
          };
        }
    
      }, [onClose]);
    
      return (
        <div className="backdrop">
          <dialog className="dialogue-window" ref={dialogRef}>
            {elements}
          </dialog>
        </div>
      );
    }
    
    export default DialogueWindow;
    

    在FileUploader.js中:它现在接受来自其父级的 onClose 属性。

    
    function FileUploader({ onClose }) {
    
      const handleCancelClick = () => {
        if (onClose) {
          onClose();
        }
      };
    
      return (
        <div className="file-uploader">
          <h2>Upload File</h2>
          {/* ... file input and status display ... */}
          <div className="file-uploader-button-container">
            <button>
              Upload
            </button>
            <button onClick={handleCancelClick}>
              Cancel
            </button>
          </div>
        </div>
      );
    }
    
    export default FileUploader;
    

    会发生什么:

    在 中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: 逃生舱口中了解有关状态和道具的更多信息

    • 3
  2. Best Answer
    Peter B
    2025-04-28T16:53:34+08:002025-04-28T16:53:34+08:00

    典型的做法是添加一个状态变量来确定是否<DialogueWindow />渲染。

    状态变量将通过一个函数进行控制,该函数需要从父级传递到Cancel按钮所在的位置。

    您可能还需要onClose在成功上传后调用,以防止对话框永远显示。

    App.js:

    import { useState } from "react";
    import DialogueWindow from "./DialogueWindow";
    import FileUploader from "./FileUploader";
    
    function App() {
      const [showUploader, setShowUploader] = useState(true);
    
      const closeUploader = () => setShowUploader(false);
    
      return (
        <div>
          {showUploader &&
            <DialogueWindow
              elements={<FileUploader onClose={closeUploader} />}
            />
          }
        </div>
      );
    }
    

    FileUploader.js:

    function FileUploader({ onClose }) {
      ...
      return (
        <div className="file-uploader">
          ...
          <div className="file-uploader-button-container">
            <button>Upload</button>
            <button onClick={onClose}>Cancel</button>
          </div>
        </div>
      );
    }
    export default FileUploader;
    
    • 2

相关问题

  • 合并排序不起作用 - Javascript代码:即使在调试后也无法找到错误

  • select.remove() 方法工作得很奇怪[关闭]

  • useOpenWeather() 中总是出现 401 res -react-open-weather lib [重复]

  • 输入元素没有只读属性,但字段仍然不可编辑[关闭]

  • 如何编辑 D3.js RadialTree 的第一个节点半径?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve