sajad torkamani

What are refs?

Refs give you a way of accessing DOM nodes or React elements that are created in the render method of a component.

What to use refs for?

  • Store a reference to a DOM node. Useful for managing focus, text selection, or media playback (e.g., myInputRef.focus()).
  • Integrating with third-party DOM libraries. Many libraries require you to imperatively operate on a DOM node (e.g., mySelectEl.initializeFancyPlugin()).

Use refs in class components

Add a ref to a DOM element

You typically assign refs to an instance property so that they can be referenced throughout the component

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    // create a ref to store the textInput DOM element
    this.textInput = React.createRef();
    this.focusTextInput = this.focusTextInput.bind(this);
  }

  focusTextInput() {
    // Explicitly focus the text input using the raw DOM API
    // Note: we're accessing "current" to get the DOM node
    this.textInput.current.focus();
  }

  render() {
    // tell React that we want to associate the <input> ref
    // with the `textInput` that we created in the constructor
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

Add a ref to a class component instance

You can also assign refs to a mounted instance of a class component. In the example below, this.textInput will refer to the mounted instance of CustomTextInput:

class AutoFocusTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();
  }

  componentDidMount() {
    this.textInput.current.focusTextInput();
  }

  render() {
    return (
      <CustomTextInput ref={this.textInput} />
    );
  }
}

This will only work if CustomTextInput is a React class component.

Access a ref

const node = this.myRef.current;

The value of current will be:

  • The underlying DOM element when the ref is used on a DOM element.
  • The mounted instance of the component when the ref is used on a custom class component.

Use refs in function components

function CustomTextInput(props) {
  // textInput must be declared here so that the ref is accessible
  // in the JSX returned below
  const textInput = useRef(null);
  
  function handleClick() {
    textInput.current.focus();
  }

  return (
    <div>
      <input
        type="text"
        ref={textInput} />
      <input
        type="button"
        value="Focus the text input"
        onClick={handleClick}
      />
    </div>
  );
}

Refs and the component lifecycle

Ref assignments are made before the componentDidMount and componentDidUpdate lifecycle methods. This means you’ll have access to any refs inside those methods.

When a component unmounts, refs are set to null.

Callback refs

Instead of directly passing the ref created from React.createRef to the ref JSX attribute, you can also pass a callback function. This function receives the underlying DOM node or component instance as an argument.

Ref callbacks may sometimes be preferable when you need to:

  • Store a reference directly in an instance property and so avoid using the createRef or current(). Mainly to improve code readability.
  • Run code when React attaches or detaches a ref to a DOM node. This can be useful when integrating with third-party DOM libraries.

Here’s an example usage of ref callbacks:

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);

    this.textInput = null;

    this.setTextInputRef = element => {
      this.textInput = element;
    };

    this.focusTextInput = () => {
      // Focus the text input using the raw DOM API
      if (this.textInput) this.textInput.focus();
    };
  }

  componentDidMount() {
    // autofocus the input on mount
    this.focusTextInput();
  }

  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={this.setTextInputRef}
        />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

The callback will be called with the underlying input element when the component mounts, and with null when it unmounts.

Pass refs between components using callback refs

Callback refs also let you pass refs between components like so:

function CustomTextInput(props) {
  return (
    <div>
      <input ref={props.inputRef} />
    </div>
  );
}

class Parent extends React.Component {
  render() {
    return (
      <CustomTextInput
        inputRef={el => this.inputElement = el}
      />
    );
  }
}

Other notes

Sources

Tagged: React