通过手写hooks的方式更优雅的使用antd Modal 您所在的位置:网站首页 antd框架model弹出页面 通过手写hooks的方式更优雅的使用antd Modal

通过手写hooks的方式更优雅的使用antd Modal

2024-04-18 02:25| 来源: 网络整理| 查看: 265

antd官网提供了弹窗的功能,同时也提供了一些简洁的确认框询问用户,如Modal.conform,Modal.info等,但是这些简洁的弹窗并不能满足复杂的form表单场景,如果使用普通的对话框,每次需要一个弹窗的时候,都要显式的设置如下一堆模版代码:

const App: React.FC = () => { const [isModalOpen, setIsModalOpen] = useState(false); const showModal = () => { setIsModalOpen(true); }; const handleOk = () => { setIsModalOpen(false); }; const handleCancel = () => { setIsModalOpen(false); }; return ( Open Modal Some contents... Some contents... Some contents... ); }; export default App;

在做内部项目中,我们经常需要使用弹窗来添加,删除,更新一些内容,甚至同一个页面需要多个弹窗的情况,每次调用弹窗的时候,都写一堆模版代码显然不够优雅,怎么能够每次通过类似Modal.confirm的方式弹出弹窗,点击关闭的时候关闭弹窗呢,而不需要写一堆模版代码的?

目标是将visible,onOk, onCancel等操作封装在子组件中,父组件只需要通过modal.open的方式调用即可。通过react hooks实现一个useModal的方式实现。 具体代码实现:

import React, { forwardRef, memo, useCallback, useImperativeHandle, useState, useRef, useMemo } from 'react'; import { Modal, Form } from 'antd'; import type { ModalProps } from 'antd/lib/modal'; import "antd/dist/antd.css"; const ModalWrap = memo(forwardRef((props: any, ref: any) => { const [form] = Form.useForm(); const [modalChildren, setModalChildren] = useState(null); const [modalProps, setModalProps] = useState({ visible: false, }); const typeRef = useRef(); const onFinish = useCallback((values: any) => { console.log(values, 'onFinish'); modalProps.onOk && modalProps.onOk(values); }, [form, modalProps]); const onClose = React.useCallback(() => { setModalProps((source: any) => ({ ...source, visible: false, })); setModalChildren(null); }, [form]); const onOpen = useCallback(() => { setModalProps((source: any) => ({ ...source, visible: true, })); }, [form]); useImperativeHandle(ref, () => ({ injectChildren: (element: React.ReactElement) => { // 用于注入子组件 setModalChildren(element); }, injectModalProps: (props: any) => { // 用于注入modal的props setModalProps((source: any) => ({ ...source, ...props, }) ) }, open: onOpen, close: onClose, setFieldsValue: (values: any) => { form.setFieldsValue(values); }, setType: (type: string) => { typeRef.current = type; } }), []); const handleOk = useCallback((e: any) => { console.log(typeRef?.current, form, form.getFieldsValue(true), 'typeRef?.current'); if (typeRef?.current === 'form') { form.submit(); } else { modalProps.onOk && modalProps.onOk(e); } }, [form, modalProps]); return ( {modalChildren ? React.cloneElement(modalChildren, { form, onFinish, onClose, }) : null } ); })); interface modalRefType { open: () => void; close: () => void; injectChildren: (child: React.ReactElement) => void; injectModalProps: (props: ModalProps) => void; setFieldsValue: (values: any) => void; setType: (type: string) => void; } interface openArgType extends ModalProps { children?: React.ReactElement, type?: 'form' | 'default', initialValues?: { [key: string]: any; }, } const useModal = () => { const modalRef = useRef(); const open = ({ children, type, initialValues, ...rest }: openArgType) => { console.log('open', modalRef); modalRef?.current?.setType(type); modalRef?.current?.injectChildren(children); modalRef?.current?.injectModalProps(rest); modalRef?.current?.open(); if (initialValues && type === 'form') { modalRef?.current?.setFieldsValue(initialValues); } }; const close = useCallback(() => { modalRef.current.close(); }, []); const modal = useMemo(() => ({ open: open, close: close, }), []); const ModalDOM = ; return [ modal, ModalDOM, ] as const; } export default useModal; //使用方式 const TestModal = () => { const [modal, useModal] = useModal(); const [form] = Form.useForm(); const onHandleClick = () => { modal.open({ title: '打开Modal', children: , onOk: (values)=>{ modal.close(); } }) } return ( 点击弹窗 ) } export default TestModal;

参考链接:www.jianshu.com/p/a26a73dbd…



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有