forwardRef 和 useImperativeHandle 用法

1,119 阅读1分钟

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;
});