1.0.1 • Published 6 years ago
react-promisify-modal v1.0.1
React-Promisify-Modal
命令式打开对话框, 并用 promise 返回结果
开始使用
安装
npm install -S react-promisify-modal
or
yarn add react-promisify-modal使用
openModal(({show, onOk, onCancel}) => (
  <Modal
    title="对话框"
    visible={show}
    onOk={() => onOk('finally')}
    onCancel={onCancel}
  >
      ...
  </Modal>))
.then(result => {
  // 使用 result
  ...
})Demo
特性
openModal直接打开对话框openModal返回一个promise, 在then方法里可以用到对话框的返回值- 支持打开多重对话框
 Modal安装在当前组件树里, 共享context- 使用
typescript开发(暂时没有办法约定返回值类型, 后面会想办法补上) - 无依赖, 含类型注释共 143 行
 
限制:
- 暂时只支持模态对话框, 非模态对话框可能关闭顺序有问题
 - 由于用到了
hooks, 因此只支持react 16.8.0以上版本 
思考
某复杂前端项目, 需要连续打开三层对话框, 每层对话框都要使用父容器的状态\
可想而知, 无论如何优化, 父容器都非常臃肿, 而且操作非常不顺畅\
后来采用渲染对话框到document.body, 脱离当前渲染树的黑客式做法, 转换成promise写法, 操作非常连贯\
美中不足的是: 这样对话框无法用到context
另外有几个项目也做到了将 modal 转换为 promise, 但有的不支持多modal, 有的局限太大, 都不满足需求
所以有了本项目
原理
TODO
使用教程
1. 安装
npm install --save react-promisify-modal2. 基础设置
需要在根组件上配置ModalProvider:
App.ts
import { ModalProvider } from 'react-promisify-modal';
const App = () => (
  <ModalProvider>
    <Page />
  </ModalProvider>
);Page.ts
import React, {useContext}from 'react';
import {ModalContext, openModal} from 'react-promisify-modal';
const openModalCallback = () => {
  ...
  这里是打开对话框的语句, 见 第3步
  ...
}
return <Button onClick={openModalCallback}>打开对话框</Button>3. 写 openModalCallback 方法
最简单的写法:
const openModalCallback = () => {
  // 第四步: 直接用 openModal 打开对话框, 并通过then获取返回值
  openModal(({ show, onOk, onCancel }) => {
    return (
      <Modal
        title="Basic Modal"
        visible={show}
        // 第五步: 通过onOk回传结果
        // onOk 可以用在 按钮 或 其它ui元素 中, 比如: <button onClick={()=>onOk(42)}
        // onOk 当然也可以用在异步方法里 , 比如 : save({}).then(result => onOk(result))
        // 它仅是一个方法
        onOk={() => onOk('finally')}
        onCancel={onCancel}
      >
        <p>Some contents...</p>
        <p>Some contents...</p>
        <p>Some contents...</p>
      </Modal>
    );
  })
    // 第六步: 对话框关闭后, 可以通过then接收到 第五步 的内容
    .then(result => console.log(result)); // <== 打印 'finally'进阶写法:
注意openModal的参数, 其实是一个FunctionalComponent, 其签名为:
type PromisifyModalProps<R> = {
  show: boolean;
  onOk: onOkHandler<R>;
  onCancel: onCancelHandler;
};
type PromisifyModal<R = any> = React.FC<PromisifyModalProps<R>>;所以你完全可以使用一个函数式组件, 避免将所有内容放在一起\ 那么, 如果对话框使用函数式组件, Modal 如何使用 Page 的内容状态呢? 通过属性下传即可( TODO: 补示范代码 )
License
MIT © g770728y