Yone
Yone

Reputation: 2134

React refs how are they used, and when are they used?

Hello and thank you for reading this question!

I have been learning React for some weeks and I have difficulties trying to understand how refs can get React's instance and put it into a JS variable.

For example we could discuss the documentation's example:

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.focusTextInput = this.focusTextInput.bind(this);
  }

  focusTextInput() {
    // Explicitly focus the text input using the raw DOM API
    this.textInput.focus();
  }

  render() {
    // Use the `ref` callback to store a reference to the text input DOM
    // element in an instance field (for example, this.textInput).
    return (
      <div>
        <input
          type="text"
          ref={(input) => { this.textInput = input; }} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

I understand that the ref gets the input element which will be rendered and stores it into a class field using this.textInput.

However I do not understand why the parameter being passed to the refs is (input) what could happen if there were jsx tags nested? For example two inputs?

Also is there not a clear way to reference the elements being created with React render/return? I am talking about something like object oriented programming: className.instanceName or creating instance from the HTML elements with: new elementName().

Thank you for your help!

Upvotes: 2

Views: 1570

Answers (2)

Shubham Khatri
Shubham Khatri

Reputation: 281656

React supports a special attribute that you can attach to any component. The ref attribute takes a callback function, and the callback will be executed immediately after the component is mounted or unmounted.

When you write

<input
      type="text"
      ref={(input) => { this.textInput = input; }} />

React extracts the ref attribute and invokes a callback after the component is mounted. In that callback function react passes the instance of the input, which is what you get as the parameter here. Think of the above as a function

<input
      type="text"
      ref={this.callback} />

and that callback will look like

const callback = (input) => { 
   this.textInput = input; 
}

According to the docs:

When the ref attribute is used on an HTML element, the ref callback receives the underlying DOM element as its argument.

Regarding your next question:

However I do not understand why the parameter being passed to the refs is (input) what could happen if there were jsx tags nested

The parameter being passed to div is just referenced as input in your example, you can call it anything you want, like input, inputRef, instance

In multiple jsx tags are nested, the ref is applied on the element on which ref attribute is passed. For instance

<div ref={this.getRef}>
   <div>Hello React</div>
</div>

The ref gets the instance of is applied to the outer div from which you can access the child elements.

Codesandbox

Also is there not a clear way to reference the elements being created with React render/return

Well refs is a way provided by React to reference, elements being created. However you should only use refs when

  • Managing focus, text selection, or media playback.
  • Triggering imperative animations.
  • Integrating with third-party DOM libraries.

Most often, props are the only way that parent components interact with their children. To modify a child, you re-render it with new props. For example if you wish to change the class on an element, instead of getting an access to the element and changing it class, you would pass the dynamic prop to it instead like

<div className={this.props.className} />

Or as a matter of fact, use state to make necessary updates

Upvotes: 2

Jeff Storey
Jeff Storey

Reputation: 57192

To explain what is happening with the ref tag, let's break it down into smaller pieces...

This block:

<input
      type="text"
      ref={(input) => { this.textInput = input; }} />

Says to call this (input) => { this.textInput = input; } when this input field is mounted and unmounted. The (input) is just a parameter name, and you could call it whatever you want. So you could rewrite it as:

<input
          type="text"
          ref={(myinputfield) => { this.textInput = myinputfield; }} />

And it will do the same thing. In both case, input and myinputfield both reference the text field on which the ref attribute was defined.

For your second question,

Also is there not a clear way to reference the elements being created with React render/return? I am talking about something like object oriented programming: className.instanceName or creating instance from the HTML elements with: new elementName().

The react model is a bit different. state is the primary way to have components interact with each other, rather than one component calling another. It's not entirely clear what you're trying to do, but when you want to update one component based on some action another component does, you would typically update the state, which would re-render the components with the new state.

You can still lookup other components in the DOM, but I'd encourage you to think more in the react model that uses state to update components.

Upvotes: 0

Related Questions