React .forwardRef()源码解析 如何实现的?

2,656 阅读1分钟

作用

可以使得在父组件中可以得到子组件中的dom节点

使用

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

demo 可以输出一个button的元素

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

class App extends Component {
	constructor(){
    super();
    this.myBtn = React.createRef();
  }

  componentDidMount() {
    console.log(this.myBtn.current);
  }

  render() {
    return (
      <Child ref={this.myBtn}>点击</Child>
    );
  }
}

export default App;

原理

  1. 首先在父组件中通过React.createRef的方式创建一个myBtn
  2. 将myBtn在子组件Child中通过制定ref={myBtn}的形式传递下去
  3. 然后子组件的方法中,会接受传递过来的ref作为实参, 然后赋给子组件的DOM
  4. 在父组件中的myBtn关联相应的dom节点之后,就可以通过current属性在父组件中得到子组件的dom节点.

React.forwardRef 的实现:

父组件myBtn——>React.forwardRef中的实参——>通过forwardRef方法创建的子组件中的ref——>指向子组件中的dom节点

React.forwardRef 的源码:

import {REACT_FORWARD_REF_TYPE} from 'shared/ReactSymbols';

import warning from 'fbjs/lib/warning';

export default function forwardRef<Props, ElementType: React$ElementType>(
  render: (props: Props, ref: React$ElementRef<ElementType>) => React$Node,
) {
  if (__DEV__) {
    warning(
      typeof render === 'function',
      'forwardRef requires a render function but was given %s.',
      render === null ? 'null' : typeof render,
    );

    if (render != null) {
      warning(
        render.defaultProps == null && render.propTypes == null,
        'forwardRef render functions do not support propTypes or defaultProps. ' +
          'Did you accidentally pass a React component?',
      );
    }
  }

  return {
    $$typeof: REACT_FORWARD_REF_TYPE,
    render,
  };
}