useImperativeHandle 与 ref

最近在用umi3.0 + antd4.0 重构以前用vue2.5写的项目。

想要的结果

const editModalRef = useRef<IEditModalRef>();
<EditModal ref={editModalRef}></EditModal>

可以通过editModalRef.current.showModal(true); 显示模态框,

EditModal 代码如下

import TNotes from '../../TNotes';
import {
  useState,
  useImperativeHandle,
  forwardRef,
  ForwardRefRenderFunction,
} from 'react';
import { Modal } from 'antd';
import React from 'react';

export interface IEditModalProps {}

export interface IEditModalState {
  visible: boolean;
  data: TNotes;
  added: boolean;
}
export interface IEditModalRef {
  showModal: ( data?: TNotes) => void;
}
const defaultState: IEditModalState = {
  added: false,
  visible: false,
  data: {
    content: '',
    loadCount: 0,
    base64: {},
    createTime: null,
    updateTime: null,
    title: '',
  },
};

export const EditModal: ForwardRefRenderFunction<
  IEditModalRef,
  IEditModalProps
> = (props, ref) => {
  const [state, setState] = useState(defaultState);
  useImperativeHandle(ref, () => ({
    showModal: (data) => {
      setState((preState) => ({
        ...preState,
        visible:true,
        ...(data ? { data } : { added: true }),
      }));
    },
  }));
  function onCancel() {
    setState(defaultState);
  }
  const title = state.added ? '添加记事' : '编辑记事';
  return (
    <Modal
      visible={state.visible}
      title={title}
      onCancel={onCancel}
    ></Modal>
  );
};
export default forwardRef(EditModal);

还是复杂在类型声明上,其实forwardRef点进去后

function forwardRef<T, P = {}>
  (render: ForwardRefRenderFunction<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;

render: ForwardRefRenderFunction<T, P> 就明确的说明了类型,只是我没反应过来只要加上这个声明就可以了...

另外泛型T代表ref的类型,P代表props的类型也秀到了我...

ForwardRefRenderFunction 是这样的

interface ForwardRefRenderFunction<T, P = {}> {
        (props: PropsWithChildren<P>, ref: ((instance: T | null) => void) | MutableRefObject<T | null> | null): ReactElement | null;

PropsWithChildren 是这样的

type PropsWithChildren<P> = P & { children?: ReactNode };