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。
相关产品推荐
相关产品推荐

