为什么,确切地说,我们需要 React.forwardRef?

IT技术 reactjs react-native
2021-04-02 03:32:55

假设我有一个带有可滚动子组件的组件,我想公开滚动的能力:

const MyComponent = (props) => {
    return <ScrollView ... />
}

我希望能够做到

<MyComponent ref={myRef} />

...

myRef.scrollTo({x: 0});

所以我需要一种方法将 ref 转发到<ScrollView>. 让我们尝试将 ref 放在 props 上:

const MyComponent = (props) => {
    return <ScrollView ref={props.scrollRef} ... />
}

...

<MyComponent scrollRef={myRef} />

...

myRef.scrollTo({x: 0});

我刚刚在 iOS 上用 React Native 尝试过,它确实有效。我看到了几个优点React.forwardRef

  • 更简单,因为我不需要使用另一个 React API。
  • 如果有多个孩子需要参考转发,也可以使用。
  • 在我看来,这种方法是

有什么好处React.forwardRef为什么在 React 16.3 中添加它?

1个回答

请注意,使用另一个命名props(例如innerRef FOR FORWARDING)没有区别,它的工作原理相同。


重构类组件

由于 React 转向函数组件(钩子),您可能希望在不破坏 API 的情况下将类组件代码重构为函数组件

// Refactor class component API to function component using forwardRef
<Component ref={myRef} />

React.forwardRef 将是您唯一的选择(进一步详细解释)。

干净的API

作为库作者,您可能需要一个可预测的API 进行ref转发。

例如,如果你实现了 aComponent并且有人想给它附加一个 ref,他有两个选项,具体取决于你的 API:

<Component innerRef={myRef} />
  • 开发人员需要知道有一个用于转发的自定义props
  • innerRef附加到哪个元素我们不知道,应该在 API 中提到或者我们console.log(myRef.current)

<Component ref={myRef} />
  • 默认行为类似于refHTML 元素上使用的 prop,通常附加到内部包装器组件。

请注意,React.forwardRef 可用于功能组件和 HOC(对于类组件,请参阅下面的替代方案)。

Ref 转发不仅限于 DOM 组件。您也可以将引用转发到类组件实例。

对于函数组件,forwardRef有时会带有useImperativeHandle组合(在类组件中,您只需在 ref 实例上调用类方法:ref.current.myAttr().

// Same usage
<Component ref={myRef} />

const Component = React.forwardRef((props, ref) => {
  // you can forward ref <div ref={ref} />
  // you can add custom attributes to ref instance with `useImperativeHandle`
  // like having ref.myAttribute() in addition to ones attached to other component.
});

重要行为refprops没有forwardRef

对于类组件,仅此代码就会将 ref 附加到CLASS INSTANCE,这本身没有用,并且需要另一个 ref 进行转发:

// usage, passing a ref instance myRef to class Component
<Component ref={myRef} />

完整示例,检查日志:

// We want to forward ref to inner div
class ClassComponent extends React.Component {
  innerRef = React.createRef();
  render() {
    // Notice that you can't just `this.props.ref.current = node`
    // You don't have `ref` prop, it always `undefined`.
    return <div ref={this.innerRef}>Hello</div>;
  }
}

const Component = () => {
  const ref = React.useRef();

  useEffect(() => {
    // The ref attached to class instance
    console.log(ref.current);
    // Access inner div through another ref
    console.log(ref.current.innerRef);
  }, []);

  return <ClassComponent ref={ref} />;
};

编辑 React 模板(分叉)

在函数组件中,它甚至不起作用,因为函数没有实例。

默认情况下,您不能在函数组件上使用 ref 属性,因为它们没有实例。[1]

refs 通常不适用于函数组件吗?还是只是参考转发?
2021-05-26 03:32:55
使用属性 ref 的 Refsref={ref}不适用于功能组件 :-) 您必须React.forwardRef在它们上使用
2021-05-30 03:32:55
@Vencovsky 我更新了答案,里面有一些错误
2021-06-08 03:32:55
开始变得更清晰了,谢谢 :-) 然而,他们本可以ref在函数组件中作为第二个参数添加而不是实现 ref 转发,对吗?这不会破坏任何现有代码,因为在此之前没有第二个参数。但是因为他们看到了裁判转发的其他优势,所以他们就这样做了。
2021-06-12 03:32:55
相反,您应该提出问题而不是在评论中进行。
2021-06-19 03:32:55