Refs

Linked Projects:

Calreact

✨ 1 person thanked Hrishi Mittal for this tutorial.

đź‘Ť Send Thanks
 
Now I want to quickly touch on the topic of refs.

Typically in React, we send data from parent components to child components via props. To modify a child, we re-render it with new props. But sometimes we may need to directly access a DOM element to modify it outside of a typical data flow, and that’s when we use refs.

Refs are often used for directly getting the value of an input field from a form, for setting the focus of a field in response to a user action, or for animations or integrations with 3rd party DOM libraries.

The React documentation has a good example of setting and using a ref.

In this example, the ref being set is called textInput. It’s then being used in the focus method to set the focus to that input field in response to a button click. This is called a callback ref.

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

  focus() {
    // 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.focus}
        />
      </div>
    );
  }
}

You could also use a string ref, but those are being phased out, so it’s best not to use them.

Let’s try it in our AppointmentForm component. We could define a string ref simply by specifying a name titleInput. We would be able to use this in our component as this.refs.titleInput.

return (
  <div>
    <h2>Make a new appointment</h2>
    <form onSubmit={this.handleSubmit}>
      <input name='title' placeholder='Appointment Title'
        ref='titleInput'
        value={this.props.title.value}
        onChange={this.handleChange} />

But it's better to use a callback ref:

return (
  <div>
    <h2>Make a new appointment</h2>
    <form onSubmit={this.handleSubmit}>
      <input name='title' placeholder='Appointment Title'
        ref={(input) => { this.titleInput = input }}
        value={this.props.title.value}
        onChange={this.handleChange} />

This ref is available to us in any of our methods.

So, in our AppointmentForm component, instead of calling e, we can use this.titleInput.

handleChange = (e) => {
  const fieldName = e.target.name;
  const fieldValue = e.target.value;
  this.props.onUserInput(fieldName, fieldValue, 
                          AppointmentForm.formValidations[fieldName]);
}

handleChange = (e) => {
  const fieldName = this.titleInput.name;
  const fieldValue = this.titleInput.value;
  this.props.onUserInput(fieldName, fieldValue, 
                          AppointmentForm.formValidations[fieldName]);
}

To demonstrate the use of this ref, let’s add a new button which we can click to focus the cursor in the title input field. You can copy and paste this button code into the AppointmentForm render function from the React example. It calls focus onClick.

<input
  type="button"
  value="Focus the text input"
  onClick={this.focus}
/>

Then add the focus method:

focus = () => {
  //Explicitly focus the text input using the raw DOM API
  this.titleInput.focus();
}

Now if we click on the "Focus the text input" button in our app, the cursor gets focused in the title input field.

This is just a way of directly accessing the DOM element.

You have to be a bit careful with using refs, because it seems like an easy shortcut to “get things done”. But if we start manipulating the DOM directly, we quickly lose the benefits of using React.

It’s best to use refs sparingly.

We don't really need to use refs in our app, so it's best to remove this code. Still, it was a good way to demonstrate how to use refs.

Liked this tutorial? Get more like this in your inbox