美文网首页
告别Modal状态管理的烦恼,拥抱命令式弹窗新时代

告别Modal状态管理的烦恼,拥抱命令式弹窗新时代

作者: 修齐治平zzr | 来源:发表于2025-11-04 22:14 被阅读0次

在现代前端开发中,弹窗(Modal)是用户交互的重要组成部分。然而,随着业务复杂度的提升,我们常常遇到以下场景:

一个页面中多个弹窗,状态管理混乱

弹窗与触发按钮逻辑分散,维护困难

重复编写控制弹窗显示的布尔状态和开关函数

特别是在使用Ant Design(antd)这样的UI库时,我们通常需要为每个Modal维护一个visible状态和一个控制该状态的函数。这导致我们的组件代码充斥着大量的useState和条件渲染,使得代码冗长且难以维护。

有没有一种方法,可以让我们像调用函数一样简单地打开弹窗,而无需在组件中维护这些状态呢?

答案是肯定的。本文将介绍一种基于React Hooks的解决方案——createHooks。通过这个自定义钩子,我们可以将弹窗的调用方式从声明式转变为命令式,从而极大地简化代码结构。

什么是命令式弹窗?
命令式弹窗允许我们通过函数调用直接打开弹窗,无需预先在JSX中渲染Modal组件。这种方式有以下优势:

简化状态管理:不再需要为每个弹窗维护一个visible状态。

逻辑内聚:弹窗的触发逻辑和弹窗内容可以封装在一起。

代码简洁:减少模板代码,使组件更清晰。

createHooks的设计思路
createHooks是一个工厂函数,它接收一个Modal组件并返回一个命令式调用的函数。这个函数可以直接在事件处理函数中调用,并能够传递参数给Modal组件。同时,它还提供了更新和销毁弹窗的能力。

在本文中,我们将一步步实现createHooks,并探讨如何将其与antd Modal结合,打造一种优雅的弹窗使用方式。

让我们开始吧!

// 传统方式 ❌ 状态管理繁琐
const [visible, setVisible] = useState(false)

// 新方式 ✅ 一行代码搞定
showCreateModal({ title: '创建用户', data: userInfo })

废话不多说,直接上代码

import React, { createElement } from 'react';
import ReactDOM from 'react-dom';

interface ModalInstance {
  destroy: () => void;
  update: (props: any) => void;
}

const createHooks = <T extends Record<string, any> = {}>(
  ModalComponent: React.ComponentType<any>
) => {
  const showModal = (props?: T): ModalInstance => {
    const container = document.createElement('div');
    document.body.appendChild(container);

    let currentProps = { ...props, open: true };

    const destroy = () => {
      ReactDOM.unmountComponentAtNode(container);
      if (container.parentNode) {
        container.parentNode.removeChild(container);
      }
    };

    const update = (newProps: any) => {
      currentProps = { ...currentProps, ...newProps };
      render(currentProps);
    };

    const render = (props: any) => {
      const element = createElement(ModalComponent, {
        ...props,
        onCancel: (...args: any[]) => {
          props.onCancel?.(...args);
          destroy();
        },
        onOk: (...args: any[]) => {
          props.onOk?.(...args);
          destroy();
        },
        afterClose: destroy,
      });
      ReactDOM.render(element, container);
    };

    render(currentProps);

    return {
      destroy,
      update,
    };
  };

  return showModal;
};

export default createHooks;

使用方式

import React from 'react';
import { Button, Space } from 'antd';
import { showSimpleModal, showCreateModal } from '../components/modals';

const TestPage: React.FC = () => {
  const handleSimple = () => {
    console.log('打开简单弹窗');
    showSimpleModal({
      title: '测试弹窗',
      onOk: () => console.log('确定'),
      onCancel: () => console.log('取消'),
    });
  };

  const handleCreate = () => {
    console.log('打开创建弹窗');
    showCreateModal({
      onOk: (values: any) => {
        console.log('创建数据:', values);
      },
    });
  };

  return (
    <div style={{ padding: 20 }}>
      <Space>
        <Button type="primary" onClick={handleSimple}>
          简单弹窗
        </Button>
        <Button onClick={handleCreate}>
          创建弹窗
        </Button>
      </Space>
    </div>
  );
};

export default TestPage;

相关文章

网友评论

      本文标题:告别Modal状态管理的烦恼,拥抱命令式弹窗新时代

      本文链接:https://www.haomeiwen.com/subject/gorxfstx.html