React将子组件的ref传给父组件的俩种方法

父组件如何获得子组件的Ref

在我们实际开发的过程当中难免会遇到父组件想要获得子组件的ref进行一些操作的时候,那么我们怎么做呢?

笔者给大家提供俩种方法:

一:使用React.forwardRef

这是react官方文档中给我们说明的,我们照着文档做即可,

笔者演示如下:

父组件代码

// 可以写俩种形式,class组件或者hook组件皆可
// class组件
import React, {Component} from 'react';
import Children from "../components/children";

export default class Test extends Component {
  constructor(props) {
    super(props);
    this.buttonRef = React.createRef();
  }
  render() {
    return (
      <div>
        我是父组件
        <p onClick={() => console.log(this.buttonRef)}>我要获取子组件button的ref</p>
        <Children ref={this.buttonRef}>我是子组件啊!!!</Children>
      </div>
    )
  }
}

// hook组件
import React, { useRef } from 'react';
import Children from "../components/children";

export default function Test(props) {
  const buttonRef = useRef();
  return (
    <div>
      我是父组件
      <p onClick={() => console.log(buttonRef)}>我要获取子组件button的ref</p>
      <Children ref={buttonRef}>我是子组件啊!!!</Children>
    </div>
  );
}

子组件代码

import React from 'react';

const Children = React.forwardRef((props, ref) => {
  return (
    <button ref={ref}>
      {props.children}
    </button>
  )
});

export default Children;

这个时候当我们点击p标签的时候就成功console出了子组件的button的ref。
在这里插入图片描述

解析:

  1. 我们通过调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量。
  2. 我们通过指定 ref 为 JSX 属性,将其向下传递给 <Children ref={ref}>。
  3. React 传递 ref 给 forwardRef 内函数 (props, ref) => …,作为其第二个参数。
  4. 我们向下转发该 ref 参数到 <button ref={ref}>,将其指定为 JSX 属性。
  5. 当 ref 挂载完成,ref.current 将指向 DOM 节点。

注意事项:
第二个参数 ref 只在使用 React.forwardRef 定义组件时存在。常规函数和 class 组件不接收 ref 参数,且 props 中也不存在 ref。
Ref 转发不仅限于 DOM 组件,你也可以转发 refs 到 class 组件实例中。

缺点:只能转发一个。

二:在子组件初始化的时候将ref通过事件传递给父组件

这个方法就是我们借用react组件数据传递和生命周期概念来进行传递ref给父组件。

笔者提供的演示代码:

父组件

import React, { useState } from 'react';
import Children from "../components/children";

export default function Test(props) {
  const [refs, setRefs] = useState([]);
  return (
    <div>
      我是父组件
      <p onClick={() => console.log(refs)}>我要获取子组件button的ref</p>
      <Children onRef={(refs) => {setRefs(refs)}}>我是子组件啊!!!</Children>
    </div>
  );
}

子组件

import React, { useRef, useEffect } from 'react';

function Children({ onRef = () => {}, children = null}) {
  const buttonRef = useRef();
  const aRef = useRef();
  useEffect(() => {
    onRef([buttonRef, aRef])
  }, []);

  return (
    <div>
      <button ref={buttonRef}>
        {children}
      </button>
      <br />
      <a href="" ref={aRef}>我就是来试试</a>
    </div>
  );
}

export default Children;

这样我们就能想要传几个ref给父组件就传几个了
在这里插入图片描述

三、高阶组件转发ref

父组件

import React, { useState, useRef } from 'react';
import Children from "../components/children";

export default function Test(props) {
  const buttonRef = useRef();
  return (
    <div>
      我是父组件
      <p onClick={() => console.log(buttonRef)}>我要获取子组件button的ref</p>
      <Children ref={buttonRef}>我是子组件啊!!!</Children>
    </div>
  );
}

高阶组件

import React from 'react';

function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps);
      console.log('new props:', this.props);
    }

    render() {
      const {forwardedRef, ...rest} = this.props;
      // 将自定义的 prop 属性 “forwardedRef” 定义为 ref
      return <Component ref={forwardedRef} {...rest} />;
    }
  }

  // 注意 React.forwardRef 回调的第二个参数 “ref”。
  // 我们可以将其作为常规 prop 属性传递给 LogProps,例如 “forwardedRef”
  // 然后它就可以被挂载到被 LogProps 包裹的子组件上。
  return React.forwardRef((props, ref) => {
    return <LogProps {...props} forwardedRef={ref} />;
  });
}

export default logProps;

子组件

import React from 'react';
import LogProps from './LogProps';

const Children = React.forwardRef((props, ref) => {
  return (
    <button ref={ref}>
      {props.children}
    </button>
  )
})

export default LogProps(Children);

这样在高阶组件中在转发一下同样达到了我们的目的~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章