You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中如何用async函数await模态框两个按钮的onClick点击选择结果

实现方案

核心逻辑

通过useRef持久化存储Promise的resolve方法,打开弹窗时返回pending状态的Promise,用户点击按钮后调用resolve传递决策结果,同时关闭弹窗,调用方通过await即可拿到用户选择结果。

前置修正

原有代码第一个错误:React 函数组件不能声明为async,React函数组件必须返回JSX,直接声明为async会返回Promise导致渲染报错,先移除Example组件前的async修饰符。

具体实现步骤

  • 引入useRef和useEffect,创建存储resolve方法的ref,用于跨渲染周期保存回调
  • 改造toggleModal方法,调用时打开弹窗并返回Promise,将resolve存入ref
  • 给Modal的确认、取消按钮绑定点击事件,触发时调用resolve传递结果、关闭弹窗并清空ref
  • 添加兜底逻辑,处理弹窗非按钮点击关闭的场景(比如点击蒙层),默认返回cancel

完整代码示例

父组件Example代码

import React, { useState, useRef, useEffect } from "react";

// 移除组件前的async修饰符
const Example = () => {
  const [modalOpen, setModalOpen] = useState(false);
  // 存储Promise的resolve方法
  const modalResolveRef = useRef(null);

  const toggleModal = () => {
    setModalOpen(true);
    // 返回Promise,等待用户点击后resolve结果
    return new Promise((resolve) => {
      modalResolveRef.current = resolve;
    });
  };

  const handleDelete = () => {
    // 传递删除决策
    modalResolveRef.current?.("delete");
    setModalOpen(false);
    modalResolveRef.current = null;
  };

  const handleCancel = () => {
    // 传递取消决策
    modalResolveRef.current?.("cancel");
    setModalOpen(false);
    modalResolveRef.current = null;
  };

  // 兜底逻辑:弹窗被其他方式关闭时默认返回cancel
  useEffect(() => {
    if (!modalOpen && modalResolveRef.current) {
      modalResolveRef.current("cancel");
      modalResolveRef.current = null;
    }
  }, [modalOpen]);

  const modalStyle = {
    display: modalOpen ? "block" : "hidden",
  };

  return (
    <div>
      <button onClick={toggleModal}>打开Modal</button>
      <Modal style={modalStyle}>
        <button onClick={handleDelete}>删除</button>
        <button onClick={handleCancel}>取消</button>
      </Modal>
      {posts.map((post, index) => (
          <Post
            key={post.id}
            post={post}
            toggleModal={toggleModal}
          />
      ))}
    </div>
  );
};

export default Example;

子组件Post调用示例

在Post组件的deletePost方法中直接await父组件传入的toggleModal即可拿到决策结果:

const Post = ({ post, toggleModal }) => {
  const deletePost = async () => {
    const decision = await toggleModal();
    if (decision === "delete") {
      // 执行你的删除逻辑:调用删除接口、更新本地数据等
      console.log("删除帖子:", post.id);
    }
  };

  return <button onClick={deletePost}>删除帖子</button>;
};

注意事项

  • 每次关闭弹窗后必须清空modalResolveRef,避免内存泄漏和重复回调问题
  • 如果你的Modal组件支持点击蒙层关闭,不需要额外修改,上述兜底useEffect会自动处理该场景返回cancel

内容的提问来源于stack exchange,提问作者Jesse G。

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 21:09:01