React Hooks封装useConfirmDialog时state存放入参丢失引用问题求解
问题核心原因
- 闭包陷阱:你把初始化传入的配置存在了
useState中,后续外部传入的配置(比如绑定了最新状态的onDeleteGroup函数)不会同步到内部state,导致函数永远是初始化时的版本。 - 无限重渲染:你调用
useConfirmDialog时传入的是字面量配置对象,每次组件渲染都会生成新的对象引用,useEffect监听props依赖时每次都判定为变化,触发setState后又引发组件重渲染,陷入死循环。
可行解决方案
核心思路是用useRef存储最新的外部基础配置,避免通过setState同步外部配置带来的重渲染和闭包问题,state仅存储弹窗开关状态和showConfirmDialog传入的临时覆盖配置。
实现代码
interface IState { isDialogOpen: boolean; // 仅存储showConfirmDialog传入的临时覆盖配置 tempDialogProps?: TDialogProps; } export const useConfirmDialog = (baseProps?: TDialogProps) => { // 用ref保存最新的外部传入基础配置,每次渲染自动更新,无需触发重渲染 const latestBasePropsRef = useRef<TDialogProps>(baseProps || {}); latestBasePropsRef.current = baseProps || {}; const [state, setState] = useState<IState>({ isDialogOpen: false, tempDialogProps: undefined }); const setIsDialogOpen = (isOpen = true) => { setState(prev => ({ ...prev, isDialogOpen: isOpen })); }; const showConfirmDialog = (tempDialogProps?: TDialogProps) => { setState(prev => ({ ...prev, tempDialogProps })); setIsDialogOpen(true); }; // 合并配置优先级:内置属性 > 临时覆盖配置 > 外部基础配置 const mergedDialogProps = { ...latestBasePropsRef.current, ...state.tempDialogProps, isOpen: state.isDialogOpen, onClose: () => setIsDialogOpen(false) }; return { setIsDialogOpen, showConfirmDialog, dialogProps: mergedDialogProps }; };
方案优势
- 完全解决闭包问题:外部传入的配置(包括
onPress等函数)每次渲染都会自动更新到ref中,永远取最新版本,不需要手动同步。 - 无额外重渲染:无需用
useEffect监听外部配置更新,自然不会触发无限重渲染。 - 兼容原有使用方式:原有调用逻辑不需要任何修改,同时保留了
showConfirmDialog临时修改配置的能力。
内容的提问来源于stack exchange,提问作者Abraham Arreola
相关产品推荐
相关产品推荐

