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

這樣在高階組件中在轉發一下同樣達到了我們的目的~

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