123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- import React, {
- useRef,
- useMemo,
- memo,
- forwardRef,
- useCallback,
- useState,
- useImperativeHandle,
- useId
- } from 'react'
- import { Modal, Form } from 'antd'
- import type { ModalProps } from 'antd'
- const MyModal = memo(
- forwardRef((prop: any, ref) => {
- const [form] = Form.useForm()
- const [modalChildren, setModalChildren] = useState<React.ReactElement>(null)
- const [loading, setLoading] = useState(false)
- const [modalProps, setModalProps] = useState<ModalProps>({
- visible: false
- })
- const typeRef = useRef<string>()
- const onFinish = useCallback(
- (values: any) => {
- const response = modalProps.onOk?.(values)
- if (response instanceof Promise) {
- setLoading(true)
- response.finally(() => {
- setLoading(false)
- })
- }
- },
- [form, modalProps]
- )
- // ant.design 4.0 Form的onFinish触发回调
- // const onFinish = useCallback(
- // (values: any) => {
- // modalProps.onOk?.(values)
- // },
- // [form, modalProps]
- // )
- // 关闭当前Modal
- const onClose = useCallback(() => {
- setModalProps(source => ({
- ...source,
- visible: false
- }))
- }, [form])
- // 关闭当前Modal
- const onOpen = useCallback(() => {
- setModalProps(source => ({
- ...source,
- visible: true
- }))
- }, [form])
- useImperativeHandle(
- ref,
- () => ({
- // 注入Modal的子组件
- injectChildren: element => {
- setModalChildren(element)
- },
- // 注入Modal参数
- injectModalProps: props => {
- console.log(props)
- setModalProps(source => {
- return {
- ...source,
- ...props
- }
- })
- },
- // 打开Modal
- open: () => {
- onOpen()
- },
- // 关闭Modal
- close: () => {
- if (loading) setLoading(false)
- onClose()
- },
- // 设置表单数据
- setFieldsValue: (values: any) => {
- form.setFieldsValue?.(values)
- },
- setType: (type: string) => {
- typeRef.current = type
- }
- }),
- []
- )
- const handleOk = useCallback(() => {
- if (typeRef.current === 'form') {
- form.submit()
- } else {
- modalProps.onOk?.(null)
- }
- }, [form, modalProps])
- // 这里的Modal是ant.design中的Modal
- return (
- <Modal {...modalProps} onCancel={onClose} onOk={handleOk} okButtonProps={{ loading }}>
- {modalChildren
- ? React.cloneElement(modalChildren, {
- onFinish,
- form,
- onClose
- })
- : null}
- </Modal>
- )
- })
- )
- 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<modalRefType>()
- const handle = useMemo(() => {
- return {
- open: ({ children, type, initialValues, ...rest }: OpenArgType) => {
- modalRef.current.setType(type)
- modalRef.current.injectChildren(children) // 注入子组件
- modalRef.current.injectModalProps(rest) // 注入Modal的参数
- modalRef.current.open()
- if (initialValues && type === 'form') {
- modalRef.current.setFieldsValue?.(initialValues)
- }
- },
- close: () => {
- modalRef.current.close()
- }
- }
- }, [])
- return [handle, <MyModal ref={modalRef} key={useId()} />] as const
- }
- export type ModalAction = {
- open: (args: OpenArgType) => void
- close: () => void
- }
- export default useModal
|