React中父组件如何调用子组件的方法?useImperativeHandle就够了

在React中要实现父组件对子组件的方法调用,离不开对React.forwardRef与useImperativeHandle的理解。 如果想直达使用方法,直接看第二点就可以了。如果想要理解透彻,请从开头看起。

1、React.forwardRef: 实现ref属性转发

React.forwardRef会创建一个React组件,能将其自身的 ref 属性转发给其后代组件。

这种技术并不常见,但在以下两种场景中特别有用:

  • 转发 refs 到 DOM 组件
  • 在高阶组件中转发 refs

React.forwardRef 接受一个渲染函数(可理解为一个组件)作为参数。这个函数的参数是props和ref,返回 React 节点。

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// 以下这个 ref 直接指向 <button>。
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
复制代码

在上述的示例中,React 会将 <FancyButton ref={ref}>元素的 ref 作为第二个参数传递给 React.forwardRef 函数中的渲染函数。该渲染函数会将 ref 传递给 元素。 即:FancyButton中的ref传给forwardRef中的ref参数,进而再传给button的ref。

画个图帮助理解:

FancyButton的ref——>FancyButton定义时的 forwraRef((props,ref))——><button ref='ref'>

因此,当 React 附加了 ref 属性之后,ref.current 将直接指向 <button>这个DOM 元素实例。

2、useImperativeHandle:将ref的实例传递给父组件。

上面讲述了ref的传递,那么我们这里讲一下如何将子组件的属性、方法传给父组件。

useImperativeHandle(ref,createHandle,[deps])
复制代码

useImperativeHandle 应当与 forwardRef 一起使用,自定义组件FancyInput,如下: 子组件:


import React, { useRef, useState, useImperativeHandle } from 'react';

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
// 等同于 const FancyInput=React.forwardRef((props,ref){...})
FancyInput = forwardRef(FancyInput);
复制代码

这样写之后,渲染 FancyInput 的父组件就可以直接调用 inputRef.current.focus()。 父组件:

const fanRef= React.useRef();

function handleClick(){
	// 在这里调用子组件的实例方法。
	fanRef.current.focus();
}
<FatherCompoent>
	<FancyInput ref={fanRef}/>
	<button onClick={handleClick}>
        Focus the input
     </button>
</FatherCompoent>
复制代码

本文主要参考React中文网,根据自己的理解加以总结。

如有帮助到您,请三连支持一下,欢迎留言。 如有不同意见,可在评论区指出,谢谢~

猜你喜欢

转载自juejin.im/post/7103749617308663816