🚀 React forwardRef:组件间的"引用传递大师"

158 阅读3分钟

🔍 什么是forwardRef?

在React的世界里, forwardRef 就像是一位"引用传递大师",它能让父组件的 ref 穿过组件层级,直接触达子组件内部的DOM元素。就像你想给住在小区深处的朋友送快递, forwardRef 就是那个能帮你穿过层层门禁的神奇通道!

🤔 为什么需要forwardRef?

在本文中,这个问题体现得淋漓尽致:

// 没有forwardRef时,这行代码会报错
<Guang title="hello" ref={ref}/>

这是因为默认情况下,函数组件就像一个封闭的盒子,父组件的 ref 无法直接穿透到组件内部的DOM元素。

🛠️ forwardRef的使用方法

让我们看看项目中的示例是如何使用 forwardRef 的:

  1. 创建一个接收ref的组件
function Guang(props, ref) {
  console.log(props, ref)
  return (
    <div>
      <input type="text" ref={ref}/>
    </div>
  )
}
  1. 使用forwardRef包装组件
// 返回一个全新的组件, 赋予它ref向下传递的能力
// 这是一个高阶组件
const WrapperGuang = forwardRef(Guang);
  1. 父组件中使用包装后的组件
function App() {
  // 父组件创建ref
  const ref = useRef(null);
  
  useEffect(() => {
    // 聚焦到子组件中的input元素
    ref.current?.focus();
  },[])
  
  return (
    <div className='App'>
      <WrapperGuang ref={ref}/>
    </div>
  )
}

🔄 forwardRef的工作原理

  1. 父组件通过 useRef 创建一个引用
  2. 这个引用被传递给 forwardRef 包装后的组件
  3. forwardRef 就像一个"快递员",将这个引用传递给内部的原始组件
  4. 原始组件将这个引用绑定到具体的DOM元素上
  5. 父组件就可以通过这个引用直接操作子组件中的DOM元素了

💡 forwardRef的使用场景

  1. 焦点控制 :就像我们的示例中那样,父组件可以直接让子组件中的输入框获得焦点
  2. 动画效果 :父组件可以直接访问子组件的DOM元素来应用动画
  3. 表单控件 :在复杂表单中,父组件可能需要直接访问子组件中的表单元素
  4. 高阶组件 :当你创建一个包装其他组件的高阶组件时, forwardRef 可以帮助你保持 ref 的传递链

🚫 没有forwardRef会怎样?

如果没有 forwardRef ,我们可能需要使用一些笨拙的方法来实现类似的功能,比如:

  • 使用回调函数来传递DOM元素的引用
  • 或者使用Context API来共享引用
  • 甚至可能需要直接操作DOM,这违背了React的设计理念

🔑 关键知识点

  1. forwardRef 只能用于函数组件
  2. 包装后的组件接收 ref 作为第二个参数(第一个参数是 props )
  3. 父组件可以像使用普通DOM元素一样使用这个 ref
  4. 记得在访问 ref.current 前检查它是否存在,避免空指针错误

🎬 总结

forwardRef 是React中一个非常实用的API,它解决了函数组件无法直接接收 ref 的问题,让组件间的引用传递变得简单而优雅。

在我们的 forward-demo 项目中,通过 forwardRef ,父组件成功地将 ref 传递给了子组件中的 input 元素,并实现了自动聚焦的功能。这就是 forwardRef 的魔力!

下次当你需要从父组件访问子组件中的DOM元素时,别忘了 forwardRef 这位"引用传递大师"哦!😉