Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why, exactly, do we need React.forwardRef?

Let's say I have a component with a scrollable subcomponent, and I want to expose the ability to scroll:

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

I want to be able to do

<MyComponent ref={myRef} />

...

myRef.scrollTo({x: 0});

So I need a way to forward the ref to the <ScrollView>. Let's try putting the ref on the props:

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

...

<MyComponent scrollRef={myRef} />

...

myRef.scrollTo({x: 0});

I just tried that with React Native on iOS, and it indeed works. I see several advantages over React.forwardRef:

  • Simpler, because I don't need to use another React API.
  • Works also if there is more than one child who needs ref forwarding.
  • Seems to me that this approach is

What's the advantage of React.forwardRef? Why was it added in React 16.3?

like image 688
cheesus Avatar asked Jul 16 '20 09:07

cheesus


People also ask

Why do we need forwardRef reaction?

The forwardRef method in React allows parent components to move down (or “forward”) refs to their children. ForwardRef gives a child component a reference to a DOM entity created by its parent component in React. This helps the child to read and modify the element from any location where it is used.

How do you use forwardRef in React?

The only way to pass a ref to a function component is using forwardRef. When using forwardRef, you can simply pass the ref to a DOM element, so the parent can access it like in example 1, or you could create an object with fields and methods using the useImperativeHandle hook, which would be similar to eample 2.

Why might you use a React ref?

Refs are a function provided by React to access the DOM element and the React element that you might have created on your own. They are used in cases where we want to change the value of a child component, without making use of props and all.

What is difference between useRef and forwardRef?

The forwardRef hooks allows React users to pass refs to child components. The ref can be created and referenced with useRef or createRef and then passed in a parent component. Using forwardRef instead of useRef is useful when a ref needs to be accessed in a parent component.


1 Answers

Note that there is no difference between using another named prop like innerRef FOR FORWARDING, it works the same.


Refactoring class components

Since React moved toward function components (hooks) you might want to refactor the class component code to a function component without breaking the API.

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

React.forwardRef will be your only option (further explained in details).

Clean API

As a library author you may want a predictable API for ref forwarding.

For example, if you implemented a Component and someone wants to attach a ref to it, he has two options depending on your API:

<Component innerRef={myRef} />
  • The developer needs to be aware there is a custom prop for forwarding
  • To which element the innerRef attached? We can't know, should be mentioned in the API or we console.log(myRef.current)

<Component ref={myRef} />
  • Default behavior similar to ref prop used on HTML elements, commonly attached to the inner wrapper component.

Notice that React.forwardRef can be used for function component and HOC (for class component see alternative below).

Ref forwarding is not limited to DOM components. You can forward refs to class component instances, too.

For function components, forwardRef sometimes comes with useImperativeHandle combo (in class component you just call the class methods on ref instance: 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.
});

Important behavior of ref prop without forwardRef.

For the class component, this code alone will attach the ref to CLASS INSTANCE which is not useful by itself and need another ref for forwarding:

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

Full example, check the logs:

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

Edit React Template (forked)

In function components, it won't even work because functions don't have instances.

By default, you may not use the ref attribute on function components because they don’t have instances. [1]

  • forwardRef.
  • Refs and the DOM.
  • Why we need ref forwarding?
like image 115
Dennis Vash Avatar answered Oct 18 '22 03:10

Dennis Vash