陌生的 react hooks (useImperativeHandle) :父组件如何获得子组件函数组件的状态和方法
前言(组件传值)
在面试中我们经常会被问到组件传值的方式,对于 React 来说,无非就以下这几种办法:
- props 传值
- ref 获取组件实例传值
- context 上下文传值
- 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 直接查看效果
参考
转载自:https://juejin.cn/post/7137904325845581860