> For the complete documentation index, see [llms.txt](https://zg-zhang.gitbook.io/note/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zg-zhang.gitbook.io/note/react/offical-website/advanced-guides/forwarding-refs.md).

# Refs 转发

Forwarding-Refs

* Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧

## 转发 Refs 到 DOM 组件

\`\`\`jsx harmony

function FancyButton(props) { return (  {props.children} ) }

````
* React 组件隐藏其实现细节，包括其渲染结果
    * 使用 FancyButton 的组件通常不需要获取内部的 DOM 元素 button 的 ref 这可以防止组件过度依赖其他组件的 DOM 结构
    * 但是这种封装对高复用的 叶 组件来说是不方便的，这些组件倾向于在整个应用中以一种类似常规 DOM button 和 input 的方式被使用 并且访问其 DOM 节点对管理焦点，选中或动画来说是不可避免的

* Refs 转发是一个可选特性，其允许某些组件接收 ref，并将其向下传递给子组件

```jsx harmony

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>
````

* FancyButton 使用 React.forwardRef 来获取传递给它的 ref，然后转发到它渲染的 DOM button
* 逐步解释：
  * 通过 React.crateRef 创建了一个 React ref 并将其赋值给 ref 变量
  * 指定 ref 为 JSX 属性，将其向下传递给 `<FancyButton ref={ref}>`
  * React 传递 ref 给 forwardRef 内函数 (props, ref) => ... 作为第二个参数
  * 向下转发 ref 参数到 `<button ref={ref}>`，将其指定为 JSX 属性
  * 当 ref 挂载完成，ref.current 将指向 button DOM 节点
* 第二个参数 ref 只有在使用 React.forwardRef 定义组件时存在，常规函数 和 class组件不接收 ref 参数，且 props 中也不存在 ref

## 组件库维护者的注意事项

* 当你开始在组件库中使用 forwardRef 时，你应当将其视为一个破坏性更改
  * 因为你的库可能会有明显不同的行为
  * 这样可能会导致依赖旧行为的应用和其他库崩溃

## 在高阶组件 HOC 中转发 refs

\`\`\`jsx harmony

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

\`\`\`
