React Refs Interview Questions

Question:

What is the purpose of Refs in React?

Answer:

Refs helps to obtain the DOM node or React Element node. For eg: if we need to select all text in a textarea, first step is to obtain the textarea object node. That can be done using Refs.

----o----

Question:

Here is a React Component that renders a textbox and a button.

class App extends React.Component {
  render() {
    return (
      <div>
        <input type="text" />
        <button>Click Me!</button>
      </div>
    );
  }
}

When the button is clicked, the textbox should get the focus. How can we do that using Refs?

Answer:

First we need to create a ref object. For that we add a constructor to the App class and use React.createRef to create a ref object.

constructor(props) {
  super(props);
  this.myRef = React.createRef();
}

Next we need to connect this.myRef with the textbox. For that add ref attribute to input element.

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

Now we need to have an event handler function for the button which gets the textbox object. The textbox node can be obtained from current property of myRef object.

clickHandler = () => {
  const textBox = this.myRef.current;
  textBox.focus();
}

After that, we need to bind the event handler function to the click event of the button. Here is the final code.

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

  clickHandler = () => {
    const textBox = this.myRef.current;
    textBox.focus();
  }

  render() {
    return (
      <div>
        <input type="text" ref={this.myRef}/>
        <button onClick={this.clickHandler}>Click Me!</button>
      </div>
    );
  }
}
----o----

Question:

Here we have a class component App. It contains a textbox and a button. When the button is clicked, the textbox gets focus using refs.

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

  clickHandler = () => {
    const textBox = this.myRef.current;
    textBox.focus();
  }

  render() {
    return (
      <div>
        <input type="text" ref={this.myRef}/>
        <button onClick={this.clickHandler}>Click Me!</button>
      </div>
    );
  }
}

Convert the App component to a functional component and implement the same functionality.

Answer:

As the first step, we create a functional App component that renders same html.

function App() {
  return (
    <div>
      <input type="text"/>
      <button>Click Me!</button>
    </div>
  );
}

To implement refs in functional component we need to use useRef() hook. useRef() hook creates a ref object.

function App() {
  const myRef = React.useRef(null);  return (
    //...
}

Now attach the myRef object to the textbox using ref attribute.

<input type="text" ref={myRef}/>

After attaching the ref to textbox, we can get the textbox node from myRef.current. Next steps are straight forward. Create a click event handler for the button and call focus() method of the textbox. Here is the final functional component.

function App() {
  const myRef = React.useRef(null);

  clickHandler = () => {
    myRef.current.focus();
  }

  return (
    <div>
      <input type="text" ref={myRef}/>
      <button onClick={clickHandler}>Click Me!</button>
    </div>
  );
}
----o----

Question:

Here we have a component that contains one div block and one button. When the button is clicked, we hide the div block.

function App() {
  const myRef = React.useRef(null);

  clickHandler = () => {
    myRef.current.style.display = "none";
  }

  return (
    <div>
      <div ref={myRef}>Backbenchers are awesome</div>
      <button onClick={clickHandler}>Hide Me!</button>
    </div>
  );
}

How can we improve this code?

Answer:

The functionality implemented can be achieved using declarative syntax of React. Above example can be done without refs. We can keep a state variable to hide the div block.

function App() {
  const [visible, setVisibility] = React.useState(true);

  clickHandler = () => {
    setVisibility(false)
  }

  return (
    <div>
      {visible ? <div>Backbenchers are awesome</div> : null}
      <button onClick={clickHandler}>Hide Me!</button>
    </div>
  );
}

Using the state approach is more efficient in rendering the component.

----o----

Question:

We have two components: <TextInput /> and <App />. TextInput renders a textbox.

const TextInput = () => (
  <div>
    <input type="text" />
  </div>
);

App component consumes TextInput.

const App = () => {
  return (
    <div>
      <TextInput />
      <TextInput />
      <button>Button 1</button>
      <button>Button 2</button>
    </div>
  );
}

When Button 1 is clicked, first textbox should get focus and when second button is clicked, second textbox should get focus. How can we do that?

Answer:

There are two approaches. First is by using forwardRef.

Here a parent component App needs to set focus on a DOM node(input) which is inside a child component(TextInput). So App needs to create a ref object and tell TextInput to forward it to input.

First step is to create a ref object in <App /> and pass it to <TextInput/>.

const App = () => {

  const inputRef1 = React.useRef(null);
  const inputRef2 = React.useRef(null);

  return (
    <div>
      <TextInput ref={inputRef1}/>
      <TextInput ref={inputRef2}/>
      <button>Button 1</button>
      <button>Button 2</button>
    </div>
  );
}

Next, update <TextInput/> to receive the ref and apply it to input textbox.

const TextInput = React.forwardRef((props, ref) => (
  <div>
    <input type="text" ref={ref}/>
  </div>
));

Now we know that inputRef1 is pointing to first textbox and inputRef2 to second textbox. We then have to add a click event to both buttons to trigger focus.

<button onClick={() => inputRef1.current.focus()}>Button 1</button>
<button onClick={() => inputRef2.current.focus()}>Button 2</button>

In the second approach, we don't have to use forwardRef. We can go with Callback Ref approach. In this case <App /> component should be a class component.