React.forwardRef没有它就已经可以了,那还有什么用呢?

React.forwardRef is already possible without it, so what's the use of it?

我对React.forwardRef这一点感到困惑。正如其 documentation 中所解释的,我知道它的主要用途是 Parent 组件 来访问 DOM Child 组件 的元素。但我已经可以做到这一点,甚至不必使用它。

这是一个代码示例,您可以将其插入 CodeSandbox 并查看它是否有效:

import React, {useRef, useEffect} from "react";
import "./styles.css";

const ChildComponent = (props) => {

  useEffect( ()=> {
    props.callbackFunction()
  })

  return(
    <div ref={props.fRef}>
      {"hello"}
    </div>
  )
}


export default function App() {
  const callbackFunction = () => {
    console.log("The parent is now holding the forwarded ref to the child div: ")
    console.log(forwardedRef)
  }

  const forwardedRef = useRef(null)

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <ChildComponent name="gravy" callbackFunction={callbackFunction} fRef={forwardedRef}/>
    </div>
  );
}

或者这里是这个例子的嵌入。老实说,我对这个有点陌生,我不知道嵌入是如何工作的,也不知道有人摆弄嵌入是否改变了我原来的沙盒,所以我犹豫要不要说。但它就在这里。 Example Forwarding Ref

在示例中,parent App() 组件成功将 ref 传递给 child,child 附加到其呈现 div。呈现后,它会调用 parent 的回调函数。 parent 然后做一个控制台日志,证明其转发的 ref 现在拥有 child 的 div。而这一切都是在没有 React.forwardRef.

的情况下完成的

那么React.forwardRef有什么用呢?

您完全正确,您可以按照您所描述的进行操作。不利的一面是您被迫公开 API (即: fRef 道具)以使其正常工作。如果您是构建应用程序的单独开发人员,这没什么大不了的,但是这可能会带来更多问题,例如。如果您正在维护一个带有 public API.

的开源库

在这种情况下,库的使用者将无法访问组件的内部结构,这意味着您必须以某种方式为他们公开组件。您可以简单地按照您在示例中的建议进行操作并添加一个命名道具。事实上,这就是库在 React 16.3 之前所做的。没什么大不了的,但是您必须将其记录下来,以便人们知道如何使用它。理想情况下,您还需要某种每个人都使用的标准,这样就不会造成混淆(许多库使用 innerRef 命名约定),但必须就此达成共识。所以都是可行的,但也许不是理想的解决方案。

使用 forwardRef,将 ref 传递给组件就像预期的那样工作。 ref prop 已经在 React 中标准化,因此您无需查看文档来弄清楚如何传递 ref 或它如何工作。但是,您描述的方法完全没问题,如果它满足您的需求,请务必采用它。

docs 中所述,它对 高度可重用的组件 很有用,这意味着组件往往像常规 HTML DOM 元素。

这对于具有大量“叶”组件的组件库很有用。你可能用过 Material UI.

示例:

假设您正在维护一个组件库。

您创建了一个 <Button/><Input/> 组件,可能只是添加了一些默认样式。

请注意这些组件 字面意思 与具有额外步骤的常规 HTML DOM 元素一样。

如果这些组件像常规 HTML DOM 元素一样使用,那么我希望所有道具都相同,包括 ref,不是吗?

如果要从 <Button/> 组件获取按钮引用,我必须通过 fRefbuttonRef 之类的东西来获取它,这不会很乏味吗?

与您的 <Input/> 相同,我是否必须查看文档才能找出要使用的 ref,它类似于 inputRef?现在还得背?

获取 ref 应该像 <Button ref={}/>

一样简单

问题

如您所知,ref 不会通过 props 传递,因为与 key 一样,React 对它的处理方式不同。

解决方案

React.forwardRef() 解决了这个问题所以我可以使用 <Button ref={}/><Input ref={}/>.