react-promisify-modal
TypeScript icon, indicating that this package has built-in type declarations

1.0.1 • Public • Published

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

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-modal

2. 基础设置

需要在根组件上配置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

Readme

Keywords

none

Package Sidebar

Install

npm i react-promisify-modal

Weekly Downloads

1

Version

1.0.1

License

MIT

Unpacked Size

51.3 kB

Total Files

8

Last publish

Collaborators

  • g770728y