--- description: Modal 命令式调用指南 globs: "**/features/**/*.tsx" alwaysApply: false --- # Modal 命令式调用指南 当需要创建可命令式调用的 Modal 组件时,使用 `@lobehub/ui` 提供的 `createModal` API。 ## 核心理念 **命令式调用** vs **声明式调用**: | 模式 | 特点 | 适用场景 | |------|------|----------| | 声明式 | 需要维护 `open` state,渲染 `` 组件 | ❌ 不推荐 | | 命令式 | 直接调用函数打开,无需 state 管理 | ✅ 推荐 | ## 文件组织结构 ``` features/ └── MyFeatureModal/ ├── index.tsx # 导出 createXxxModal 函数 ├── MyFeatureContent.tsx # Modal 内容组件 └── ...其他子组件 ``` ## createModal 用法(推荐) ### 1. 定义 Content 组件 (`MyFeatureContent.tsx`) ```tsx 'use client'; import { useModalContext } from '@lobehub/ui'; import { useTranslation } from 'react-i18next'; export const MyFeatureContent = () => { const { t } = useTranslation('namespace'); const { close } = useModalContext(); // 可选:获取关闭方法 return (
{/* Modal 内容 */}
); }; ``` ### 2. 导出 createModal 函数 (`index.tsx`) ```tsx 'use client'; import { createModal } from '@lobehub/ui'; import { t } from 'i18next'; // 注意:使用 i18next 而非 react-i18next import { MyFeatureContent } from './MyFeatureContent'; export const createMyFeatureModal = () => createModal({ allowFullscreen: true, children: , destroyOnHidden: false, footer: null, styles: { body: { overflow: 'hidden', padding: 0 }, }, title: t('myFeature.title', { ns: 'setting' }), width: 'min(80%, 800px)', }); ``` ### 3. 调用方使用 ```tsx import { useCallback } from 'react'; import { createMyFeatureModal } from '@/features/MyFeatureModal'; const MyComponent = () => { const handleOpenModal = useCallback(() => { createMyFeatureModal(); }, []); return ; }; ``` ## 关键要点 ### i18n 处理 - **Content 组件内**:使用 `useTranslation` hook(React 上下文) - **createModal 参数中**:使用 `import { t } from 'i18next'`(非 hook,支持命令式调用) ```tsx // index.tsx - 命令式上下文 import { t } from 'i18next'; title: t('key', { ns: 'namespace' }) // Content.tsx - React 组件上下文 import { useTranslation } from 'react-i18next'; const { t } = useTranslation('namespace'); ``` ### useModalContext Hook 在 Content 组件内可使用 `useModalContext` 获取 Modal 控制方法: ```tsx const { close, setCanDismissByClickOutside } = useModalContext(); ``` ### ModalHost `createModal` 依赖全局 `` 组件。项目中已在 `src/layout/GlobalProvider/index.tsx` 配置,无需额外添加。 ## 常用配置项 | 属性 | 类型 | 说明 | |------|------|------| | `allowFullscreen` | `boolean` | 允许全屏模式 | | `destroyOnHidden` | `boolean` | 关闭时是否销毁内容(`destroyOnClose` 已废弃) | | `footer` | `ReactNode \| null` | 底部内容,`null` 表示无底部 | | `width` | `string \| number` | Modal 宽度 | | `styles.body` | `CSSProperties` | body 区域样式 | ## 迁移指南 ### Before(声明式) ```tsx // 调用方需要维护 state const [open, setOpen] = useState(false); return ( <> ); ``` ### After(命令式) ```tsx // 调用方无需 state,直接调用函数 const handleOpen = useCallback(() => { createMyModal(); }, []); return ; ``` ## 示例参考 - `src/features/SkillStore/index.tsx` - createModal 标准用法 - `src/features/SkillStore/SkillStoreContent.tsx` - Content 组件示例 - `src/features/LibraryModal/CreateNew/index.tsx` - 带回调的 createModal 用法 - `src/features/Electron/updater/UpdateModal.tsx` - 复杂 Modal 控制示例