Refs 转发
Ref 转发允许某些组件接收 ref ,并将其向下传递给子组件。
const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
))
// 你可以直接获取 DOM button 的 ref :
const ref = React.createRef()
<FancyButton ref={ref}>Click me!</FancyButton>
和 key 一样,ref 不会向下传递(通过 {...props} 语句),React 会对其进行处理。不过我们可以通过 React.forwardRef 明确我们要传递的 ref :
function logProps(Component) {
  class LogProps extends React.Component {
    componentDidUpdate(prevProps) {
      console.log('old props:', prevProps)
      console.log('new props:', this.props)
    }
    render() {
      // 将 `ref` 分配给实例
      const {forwardedRef, ...rest} = this.props;
      return <Component ref={forwardedRef} {...rest} />
    }
  }
  // `React.forwardRef` 接受一个渲染函数
  // 其接收 `props` 和 `ref` 参数并返回一个 React 节点
  return React.forwardRef((props, ref) => {
    return <LogProps {...props} forwardedRef={ref} />;
  })
}
自定义 DevTool 中的显示名称
默认情况下转发组件名称为 "ForwardRef(myFunction)" ,也可以通过设置渲染函数的 displayName 属性来设置名称:
function logProps(Component) {
  class LogProps extends React.Component {
    // ...
  }
  function forwardRef(props, ref) {
    return <LogProps {...props} forwardedRef={ref} />;
  }
  // 在 DevTools 中为该组件提供一个更有用的显示名。
  // 例如 "ForwardRef(logProps(MyComponent))"
  const name = Component.displayName || Component.name;
  forwardRef.displayName = `logProps(${name})`;
  return React.forwardRef(forwardRef);
}