【问题标题】:value of using React.forwardRef vs custom ref prop使用 React.forwardRef 与自定义 ref 道具的价值
【发布时间】:2021-02-19 22:36:39
【问题描述】:

我看到 React.forwardRef 似乎是从反应文档中将 ref 传递给子功能组件的认可方式:

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

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

但是,与简单地传递自定义道具相比,这样做的优势是什么?:

const FancyButton = ({ innerRef }) => (
  <button ref={innerRef} className="FancyButton">
    {props.children}
  </button>
));

const ref = React.createRef();
<FancyButton innerRef={ref}>Click me!</FancyButton>;

我能想到的唯一优势可能是为 refs 提供一致的 api,但还有其他优势吗?传递自定义道具是否会在渲染时影响差异并导致额外的渲染,肯定不会因为 ref 在 current 字段中存储为可变状态?

例如,假设您想传递多个 ref(这可能表明代码有异味,但仍然如此),那么我能看到的唯一解决方案就是使用 customRef 道具。

我想我的问题是使用 forwardRef 而不是自定义道具有什么价值?

【问题讨论】:

    标签: javascript reactjs performance


    【解决方案1】:

    即使React docs 提到自定义 ref 属性作为forwardRef 更灵活的方法:

    如果您使用 React 16.2 或更低版本,或者如果您需要比 ref 转发提供更多的灵活性,您可以使用这种替代方法并显式传递 ref 作为不同命名的 prop。

    还有一个gist,Dan Abramov 在其中写到了它的优势:

    • 兼容所有 React 版本
    • 适用于类和函数组件
    • 简化了将 ref 传递给嵌套组件几层的过程

    我要补充一点,像往常一样传递 refs 不会导致 breaking changes 并且是多个 refs 的方式。我想到的forwardRef 的唯一优点是:

    • DOM 节点、功能和类组件的统一访问 API(您提到过)
    • ref 属性不会使你的 props API 膨胀,例如如果您使用 TypeScript 提供类型

    在渲染时传递自定义 prop 是否会影响 diffing 并导致额外的渲染?

    如果您将内联 callback ref 函数作为 prop 向下传递,则 ref 可能会触发重新渲染。但无论如何,将其定义为类实例方法或通过诸如useCallback 之类的一些记忆化是一个better idea

    【讨论】:

    • 太棒了,感谢福特,我有点想可能是这种情况,只是想对此有所了解。
    • 优势点不是引入整个 API 的足够大的理由,只是代码膨胀恕我直言
    • 这太疯狂了。函数组件忽略 ref 属性(不将其作为属性传递,并设置 current = null。因此,似乎 forwardRef() 除了鼓励组件的黑盒之外没有任何理由。
    • React.forwardRef 的主要缺点是您会丢失对组件的Props 的类型检查。至少我还没有发现如何使用 forwardRef 并继续检查传递的属性。
    【解决方案2】:

    RefReact 组件中的标准属性。

    包装其他组件以提供附加功能的某些组件,使用ref 来引用被包装的组件并期望该组件具有ref 属性。

    一个组件最好具有ref 属性以与其他组件和库兼容。

    函数组件不能有“ref”属性,必须使用forwardRef来提供ref属性。

    【讨论】:

      猜你喜欢
      • 2021-02-03
      • 2020-10-19
      • 2021-05-17
      • 1970-01-01
      • 2022-12-21
      • 2020-12-15
      • 2020-11-10
      • 1970-01-01
      相关资源
      最近更新 更多