官网文档
forwardRef : 转发 ref
useImperativeHandle : 用于自定义暴露给父组件的实例值
"react": "^17.0.2"
"@types/react": "^17.0.44"
import { FC, useEffect, useRef } from 'react';
// 导入子组件
import ChildComponent, { IRef } from './ChildComponent';
let MyConponent: FC = function () {
// 指定泛型,对 ref 进行类型约束
let testRef = useRef<IRef>(null);
useEffect(() => {
console.log(testRef);
// 调用子组件的方法
testRef.current?.MyTestFn();
});
return (
<>
<ChildComponent ref={testRef} />
</>
);
};
export default MyConponent;
import { useMemoizedFn } from 'ahooks';
import { forwardRef, memo, useImperativeHandle } from 'react';
export interface IRef {
MyTestFn: () => void;
}
export interface IProps {
myName?: string;
}
// 泛型第一个参数是 ref类型
// 第二个参数是 props 的类型 (可以不填写,默认是 { } )
// 指定上这两个类型, 享受 TypeScript 完美的开发体验
let ChildComponent = forwardRef<IRef, IProps>((props, forwardedRef) => {
// 定义一个普通方法
let test = useMemoizedFn(() => {
alert('我是子组件');
});
// 暴露给 ref 的方法
useImperativeHandle(
forwardedRef,
() => ({
MyTestFn: test,
}),
[test], // 依赖项, 同 useEffect
);
// 由于 useImperativeHandle 的 @types 中写的是 ""
// 返回值 extends 了 IRefProps 所以可以多写,ts也不会报错(比如下面的"a").
// 由于interface中没有定义"a",所以使用的时候ts会报错.难道是作者写的 bug ???
// 建议还是把"a"加到interface中获得更好的 ts 体验
// 例子:
// () => ({
// MyTestFn: test,
// a: "123ew"
// }),
return <p>子组件 {props.myName}</p>;
});
// 设置 props 的默认值
ChildComponent.defaultProps = {
myName: '小明',
};
export default memo(ChildComponent);