Vencovsky
Vencovsky

Reputation: 31565

Why can't you pass a ref to a functional component in react?

Why can't you pass a ref to a functional component in react?

What is different in function components compared to class components that you can't pass a ref to it?

Why is that not possible?

Notes: I'm making this question, because I always saw explanations about how to use ref with functional components, and that you need to use fowardRef, but no one explained how react handles functional components making it not possible to pass a ref to it, it's always explained how to do it, but never why you need to do it.

Upvotes: 16

Views: 10463

Answers (3)

Dennis Vash
Dennis Vash

Reputation: 53874

When you pass ref to a class component, it's made to point (via ref.current) to the actual class instance. (See "Accessing Refs" in the legacy React documentation.) That lets you access the fields of that instance. But function components don't have instances or fields, so there's nothing for ref to point to, and nothing it could be used for.

And, to be clear, forwardRef doesn't really change that. forwardRef still doesn't let ref point to the instance, because there still isn't one. Instead, forwardRef lets you "forward" the ref to another object: either a nested component (typically a DOM element), or a custom object that you define (using useImperativeHandle).

Presumably, if React were being designed from scratch today, ref would be done a bit differently. But because of its history — because it has a special meaning for class components — ref is reserved.

You can, however, use another prop name like innerRef and use it for forwarding, as discussed at Why, exactly, do we need React.forwardRef?.

Upvotes: 7

user31782
user31782

Reputation: 7589

Because, it doesn't make much sense for function components as they don't have this. On the other hand using ref on a class component is essentially gonna bind refObj.current to the class's instance(this) itself and access public fields and methods but not static properties/methods of that class. To elaborate on this, consider the following example:

//import { Component, createRef } from 'react';

class Mybtn extends React.Component {
   constructor(props) {
      super(props);
    }
  myprop = 33;         //Is  accessible via ref attribute
  static myprop2 = 44; //not accessible via ref attribute
  Log(){
    console.log(this.props);
  }
  render(){    
    return (      
      <button>test</button>
    )
  }
}


function Mybtn2() {
  return <button>TTT</button>;
}


class Form extends React.Component {
  inputRef = React.createRef();

  handleClick = () => {    
    this.inputRef.current.Log(); //same as calling this.Log() from inside Mybtn
    console.log(this.inputRef.current.myprop);  //instance's field
    console.log(this.inputRef.current.myprop2); //can't access static fields, but can access instance's field 
  }

  render() {
    return (
      <div>
        <input ref={this.inputRef2} />
        <button onClick={this.handleClick}>
          Handle click
        </button>
        <Mybtn ref={this.inputRef} prop1="tst"></Mybtn>
        <Mybtn2 ref={this.inputRef3} prop1="tst"></Mybtn2>
      </div>
    );
  }
}

//ReactDOM.createRoot(document.getElementById('app').render('Form')

ReactDOM.render(<Form />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="app"></div>

I am assuming, internally React binds ref attribute to the instance of class. So when it encounters ref on a function component probably babel checks if it's a class-based(instance) component or a function component.

Upvotes: 0

Tran Hoang Loc
Tran Hoang Loc

Reputation: 29

I search on google with the same question: Why cannot pass ref like a props in React? And i find out the answer at React documentation:

There is one caveat to the above example: refs will not get passed through. That’s because ref is not a prop. Like key, it’s handled differently by React. If you add a ref to a HOC, the ref will refer to the outermost container component, not the wrapped component.

https://reactjs.org/docs/forwarding-refs.html

I hope that can give you a safisfactory answer!

Upvotes: 2

Related Questions