痛点:
- 当我们在项目里面使用弹窗的时候,不可避免的会需要额外的存储一些状态,比如visible变量
- 在table操作列的时候打开弹窗有时候,需要将当前行的数据传送到弹窗里面,这时候,你不得不将当前行数据存储到state里面。
- 其它需要存储状态的情况
往期解决方案
,但是在使用的过程中,前面的方案发现了一个比较严重缺陷,就是拿不到context,因为是自己单独调用的render方法渲染的。另外一个原因现在大家版本都是react 18+ 以上,已经不推荐使用render这种方式去渲染,所以用自定义hooks的方式优化了一版本。
用法
useDialog
import React, { cloneElement, useCallback } from 'react';
export interface UserDialogProps {
closeDialog: () => void;
visible: boolean;
setVisible: React.Dispatch<React.SetStateAction<boolean>>;
}
export const useDialog = <T,>(Component) => {
const [visible, setVisible] = React.useState<boolean>(false);
const detailRef = React.useRef<any>({});
const open = useCallback((detail: T) => {
detailRef.current = detail;
setVisible(true);
}, []);
const closeDialog = () => {
setVisible(false);
};
const node = cloneElement(<Component />, {
visible,
setVisible,
closeDialog,
...detailRef.current,
});
const holder = React.useMemo(() => {
if (visible) {
return node;
}
return null;
}, [visible]);
return { open, closeDialog, holder };
};
useDialog会往传进来的组件props里面注入三个固定参数:
visible弹窗的显隐变量closeDialog关闭弹窗setVisible(通常不需要)
Modal组件
import {Modal} from 'antd';
import {UserDialogProps} from './useDialog';
export interface IModalProps extends UserDialogProps {
}
const Modal = (props) => {
const {visible, closeDialog} = props;
return <Modal
visible={visible}
onCancel={closeDialog}
>
<p>123</p>
</Modal>
}
export default Modal;
父组件
import React from 'react';
import {Button} from 'antd';
import Modal, {IModalProps} from './Modal';
import {useDialog} from './useDialog';
const App = () => {
const {open, holder} = useDialog<IModalProps>(Modal)
const handleClick = () => {
open({
// ... 传给Modal的props参数
})
}
return <div>
{holder}
<Button onClick={handleClick}></Button>
</div>
}
总结
优化的这一版目前还没有发现什么问题,对比之前render方案带来的副作用,已经全部修复了。