forwardRef 和 useImperativeHandle 用法
一般使用ref的场景,使用ref.current读取dom或者ref保存数据
1. 创建ref的方法
1.1. React.createRef()
1.2. React.useRef()
ref只在初始化的时候赋值,在组件的整个生命周期内保持不变。返回可变的ref对象,所以可以使用ref来保存数据。
function test(){
const InputRef = React.useRef()
const handleClick = ()=>{
// InputRef.current指向挂载的dom
InputRef.current?.focus()
}
return <div onClick={handleClick}>
<input type='text' ref={InputRef}/>
</div>
}
2. 函数组件如果需要传递ref只能使用forwardRef,生成高级组件来使用.
ref不能和props一样直接传递到子组件。 forwardRef是转发ref,会创建一个react组件,这个组件可以接收到父组件传递下来的ref。
如果父组件需要调用子组件的DOM实例一些方法如:focus或其他方法,可以通过ref.current来获取.
// 父组件
const Article: NextPage<IProps> = (props) => {
const modalRef = useRef<IPopupRef>(null);
return (
<>
<div onClick={() => modalRef.current?.open()}>打开弹窗</div>
<Modal title="弹窗" content={"this is a modal"} ref={modalRef} />
</>
);
};
// 创建一个popup组件
export interface ModalProps {
title: string;
content: string | React.ReactElement;
}
export interface IPopupRef {
open: () => void;
}
const Modal = forwardRef<IPopupRef, ModalProps>(({ title, content }, ref) => {
const [visible, setVisible] = useState(false);
const handlClose = () => {
setVisible(false);
};
useImperativeHandle(ref, () => ({
open: () => {
setVisible(true);
},
}));
return visible ? (
<div className={styles.modal}>
<div className={styles.mask}>
<div className={styles['modal-content']}>
<header>
<h1>{title}</h1>
<span onClick={handlClose}>X</span>
</header>
<main>{content}</main>
</div>
</div>
</div>
) : null;
});