When to use useImperativeHandle

January 05, 2021

A post by Will Mayger
Twitter . Instagram

In React, useImperativeHandle is a pretty uncommon react hook, and you would definitely be forgiven for not having used it, knowing when to use it or even what is does.

So in this post we will cover what it is, when you should use it and break it down into easy to understand english and steps you can follow to use useImperativeHandle.

So first thing is first, we need to understand what this react hook is before we can know when to use it.

What is useImperativeHandle in React?

Before we can talk about what useImperativeHandle is we need to cover a few other parts of react hooks because they are used with useImperativeHandle.

useImperativeHandle is used with refs and a ref is just a way to control a DOM element in React.

So instead of accessing an element via Vanilla Javascript we instead use refs so that we ensure React has control over these elements.

In React we can pass refs to other components using a HOC (Higher order component) called forwardRef.

I have an entire article dedicated to refs, the useRef hook and ref forwarding which you can read here: How to use useRef in React

What is imperative code?

In the official react docs for useImperitiveHandle they mention something called imperative code.

All this means is code that modifies the state of a program, in our case with useImperitiveHandle, it will modify the ref that we use elsewhere.

Great, so what does useImperitiveHandle do?

The hook useImperativeHandle lets you modify the ref instance that is exposed from parent components when using refs.

In other words, the useImperativeHandle gives you the ability to modify a ref that has been created.

For example, let’s say you have an element that you need to track whenever it gets clicked on, you could use useImperativeHandle to overwrite the native click event to do this.

So the parent creates a ref, the child modifies it with another ref and using useImperativeHandle, then the parent can use the modified ref.

Let’s walk through this step by step to help give a better understanding of what it does:

  1. You create a ref in your parent component.
  2. You forward that ref to a child component using forwardRef.
  3. You then assign this ref to an input element within the child component.
  4. Back in the parent component let’s say you have a button that if you click it will focus you on the child component’s input element.
  5. You set an onClick on the button which will call the ref’s focus function which in turn will then trigger the event you set by using useImperativeHandle.

Here is an example of useImperativeHandle in code following our step by step guide:

import React, { useRef, useImperativeHandle, forwardRef } from "react"

function sendEvent() {
  // send event on focus
  console.log("Event has been sent!")
}

export function ImperativeChildExampleComponent(props, ref) {
  // we need to create a new ref for the input to be able to focus on the element
  const inputRef = useRef(null)

  useImperativeHandle(ref, () => ({
    focus: () => {
      // send event
      sendEvent()

      // focus on the input after we send the event
      inputRef.current.focus()
    },
  }))

  return <input {...props} ref={inputRef} />
}

const ImperativeChildExample = forwardRef(ImperativeChildExampleComponent)

export default function ImperativeParentExample() {
  const ref = useRef(null)
  return (
    <div>
      <ImperativeChildExample ref={ref} />
      <button onClick={() => ref?.current?.focus()}>Focus!</button>
    </div>
  )
}

You may notice how we are actually using two refs here, the reason behind that in this example is because we still want to be able to call the focus method on the element.

If we were to use the parent ref to be able to do this, we would end up stuck in an infinite loop because whenever the focus method is called it would send the event and then call itself again and again.

This also has another benefit of protecting the ref and only allowing the parent ref access to certain functions and properties that we decide effectively creating a private scope rather than giving access to the entire ref.

This might come in useful if you create a component for a library, for example.

When to use useImperativeHandle In React?

When it comes to using useImperativeHandle, it is actually pretty rare and won’t need to be used very often.

You should generally try to avoid using this hook as well for the most part, if you feel the need to modify a native property on a ref, there will most likely be another way in which you can do this without directly modifying the ref.

For example, if you want to fire a tracking event onClick, instead of using useImperativeHandle with a forwarded ref you can try adding the onClick function as a property of that DOM element instead.

Outside of that when you need to change/modify some values within a ref of a DOM element, then it might be worth using useImperitiveHandle with a ref providing there is no other way to do this.

Finally, if you are using useImperativeHandle, then you should only use it in combination with the forwardRef HOC.

Summary

That covers it for useImperativeHandle, you may never end up needing to use this hook, but it is still useful to know what it does, what it can be used for, when and when not to use it.

Be sure to check out my other articles on react hooks below.

Will

Image icon made by Becris from www.flaticon.com