关于Modal,你的open定义在父级还是子级呢?

84 阅读2分钟

如果定义在父级是这样的

father:

const [visible, setVisible] = useState<boolean>(false)
const [modalData, setModalData] = useState<any>()
const onOpen = () => {
    // 保存状态,比如需要用
    const tmpModalData = {}
    setModalData(tmpModalData)
    setVisible(true)
}

const onClose = () => {
    // todo 清除Modal数据

    setVisible(false)
} 

<Button onClick={onOpen}>打开modal</Button>
<Modal visible={visible} onOk={onClose} onCancel={onClose} modalData={modalData}>
    modal content
</Modal>

优点:符合React数据单向流动的理念。 缺点:当Modal中需要的状态比较多,增加父组件的管理负担。(比如在table中点编辑,往往我们需要获取到当前行的数以及及一些额外的参数,管理起来作为当前modal要使用的值。)

006APoFYly8hi8n9gb9egj30b40b474e.jpg

如果在子级中定义Modal的方法,并对外暴露一个open方法,通过open方法拿到当前Modal所需要的数据,使父级与子级解耦。

father:

export interface ModalRefType<T> {
  openModal: (values: T) => void;
}
const modalRef = useRef<ModalRefType<DiskIoDetailDrawerParams> | undefined>();

// 在需要打开modal的地方执行该方法
modalRef.current?.openModal({id: 123});

// 把自定义的Modal组件放到父级中,并且绑定ref
<MyDrawer ref={modalRef} title="this is title" />

child:

import { Modal } from '@arco-design/web-react';
import { useBoolean } from 'ahooks';
import { forwardRef, useImperativeHandle } from 'react';

export interface RowDetailModalParams {
    id: number;
}
interface Props {
    title: string
}
export const RowDetailModal = forwardRef<
    ModalRefType<RowDetailModalParams>,
    Props
>((props, ref) => {
    const [visible, { setTrue, setFalse }] = useBoolean(false);
    const {title} = props
    const openModal = (values: RowDetailModalParams) => {
        const { id } = values;
        // todo
        setTrue();
    };
    useImperativeHandle(ref, () => ({
        openModal,
    }));

    return (
        <Modal
            visible={visible}
            onOk={() => {
                //todo
                setFalse();
            }}
            onCancel={() => {
                // todo
                setFalse();
            }}
            title={title}
        >
            modal content
        </Modal>
    );
});


优点:高内聚,子Modal定义了对当前要展示的数据的全部操作,对外保留openModal方法作为入口。且父组件只需要维护handleOpen的方法和一个Ref,增加父组件的代码可维护性。【一大堆useState维护起来真的眼花缭乱】

总结:

在经过把Modal的管理放到父组件,同时有时候一个页面有四五个不同Modal要打开的时候,父组件相当于要维护至少10个state【管理modal的和管理传给Modal数据的state】。 本着“人是死的,数据是活的”的想法,我坚持把Modal的管理定义在Modal内部,对外暴露一个open方法来开启Modal的使用。

如果是你,关于Modal,你的open定义在父级还是子级呢?