React自定义MUI Dialog Hook问题:Promise无法等待弹窗操作结果
问题根源
你用useState存储Promise的resolve函数,而React的useState状态更新是异步的——调用setActionCallback后,组件需要重新渲染才能让actionCallback生效。如果在组件重新渲染前点击OK,actionCallback还是undefined,Promise无法被resolve;即使渲染完成,多次调用弹窗也可能出现状态覆盖问题,导致await行为异常。
修复方案
把存储resolve函数的useState换成useRef,因为useRef的更新是同步的,无需等待组件渲染:
修改Provider组件代码
import { useRef, useState } from 'react'; // ... const DialogProvider = ({ children }: { children: React.ReactNode }) => { const [open, setOpen] = useState(false); const [title, setTitle] = useState(''); const [text, setText] = useState(''); // 用useRef替代useState存储resolve函数 const actionCallbackRef = useRef<((value: boolean) => void) | undefined>(undefined); const showAlertDialog = (title: string, text?: string): Promise<boolean> => { setOpen(true); setTitle(title); setText(text); return new Promise<boolean>((resolve) => { // 同步更新ref的current属性 actionCallbackRef.current = resolve; }); }; const handleOKClick = () => { setOpen(false); // 调用当前的resolve函数 actionCallbackRef.current?.(true); // 重置ref,避免后续误触发 actionCallbackRef.current = undefined; }; // 可选:添加取消按钮的处理逻辑 const handleCancelClick = () => { setOpen(false); actionCallbackRef.current?.(false); actionCallbackRef.current = undefined; }; return ( <DialogContext.Provider value={{ showAlertDialog }}> {children} <DialogContainer title={title} open={open} text={text} onOK={handleOKClick} onCancel={handleCancelClick} // 传递取消回调 /> </DialogContext.Provider> ); };
调用逻辑保持不变
const handleClick = async () => { console.log('dialog'); const answer = await showAlertDialog('test', 'test'); console.log(answer); // 点击OK输出true,点击取消输出false };
说明
useRef的current属性是同步更新的,调用showAlertDialog时设置的resolve函数会立即生效,点击弹窗按钮时能直接调用正确的resolve,Promise会正常完成,await也能正确等待结果。同时每次弹窗关闭后重置ref,可以避免多次调用时的函数覆盖问题。
内容的提问来源于stack exchange,提问作者momi
相关产品推荐
相关产品推荐

