likes
comments
collection
share

陌生的 react hooks (useImperativeHandle) :父组件如何获得子组件函数组件的状态和方法

作者站长头像
站长
· 阅读数 59

前言(组件传值)

在面试中我们经常会被问到组件传值的方式,对于 React 来说,无非就以下这几种办法:

  1. props 传值
  2. ref 获取组件实例传值
  3. context 上下文传值
  4. redux 等全局状态管理器传值

但是对于方法二,我们知道 class 类组件是有 ref 的,但是在 function 函数组件我们是不能使用 ref 属性的,因为他们没有实例。详见:Refs and the DOM – React

那么如果我们有这么个场景:期望在父组件能获取到某函数子组件的状态和方法,进行后续逻辑处理。

当子组件是 class 类组件时,我们很好实现,只需要为子组件设置一个 ref,在需要时 this.ref.xxx 即可拿到子组件的状态和方法

useImperativeHandle

官方解释:Hook API 索引 – React

默认情况下,你不能在函数组件上使用 ref 属性,因为它们没有实例。

如果要在函数组件中使用 ref,你可以使用 forwardRef(可与 useImperativeHandle 结合使用),或者可以将该组件转化为 class 组件。

不管怎样,你可以在函数组件内部使用 ref 属性,只要它指向一个 DOM 元素或 class 组件

总的来说,如果你想函数子组件像类子组件一样,只要给它设置 ref 就能通过 this.ref.xxx 获取到状态和方法,那么你就需要将 forwardRef 和 useImperativeHandle 结合起来。

在使用方面,以官方示例为例,第一个参数是 ref,它需要与 forwardRef 的第二个参数 ref 对应一起来;第二个参数是个回调函数,我们只需要关注这个函数是返回一个对象,对象中的内容就是届时我们调用 this.ref.xxx 时得到的值;第三个参数则是依赖项,这个可参考最常用的 react hooks useEffect 中第二个参数 deps 依赖项的用法;

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

示例代码

可将以下地址的 github.com 替换为 githubbox.com 后回车,即可导入 CodeSandbox 直接查看效果

github.com/blueju/blog…

参考

转载自:https://juejin.cn/post/7137904325845581860
评论
请登录