SoFunction
Updated on 2025-04-08

How to use useRef and useImperativeHandle in React Hooks

Analysis of useRef

useRef returns a ref object, and the returned ref object remains unchanged throughout the entire life of the component.

The most commonly used ref is two ways to use it:

Usage 1: Used to obtain the DOM (or component, but it needs to be a class component) element and operate the DOM;

import React, { memo, useRef } from 'react'
const App = memo(() => {
  const inputRef = useRef()
  function inputDom() {
    ()
  }
  return (
    <div>
      <input type="text" ref={inputRef}/>
      <button onClick={inputDom}>Get focus</button>
    </div>
  )
})
export default App

Usage 2: Save a data, and this object can be saved and unchanged throughout the entire life cycle;

For example, when we modify the counter, the App component will be re-rendered, and the info object will also open up a new memory space in the heap memory; it means that every time we modify the counter, we get a new info object

import React, { memo, useState, useRef } from 'react'
const App = memo(() => {
  const [counter, setCounter] = useState(10)
  function increment() {
    setCounter(counter + 1)
  }
  // Define an object  const info = {}
  return (
    <div>
      <h2>Current count: {counter}</h2>
      <button onClick={increment}>+1</button>
    </div>
  )
})
export default App

We can use useRef, because no matter how many times the useRef is rendered, the return is the same ref object.

import React, { memo, useState, useRef } from 'react'
const App = memo(() => {
  const [counter, setCounter] = useState(10)
  function increment() {
    setCounter(counter + 1)
  }
  // Define an object  const infoRef = useRef()
  return (
    <div>
      <h2>{}-{}</h2>
      <h2>Current count: {counter}</h2>
      <button onClick={increment}>+1</button>
    </div>
  )
})
export default App

UseRef and useCallback can be solvedClosure TrapThe problem, there are corresponding cases in the previous article

useImperativeHandle

useImperativeHandle is not very easy to understand, it is a bit abstract, let's learn it bit by bit

Let's first review the combination of ref and forwardRef:

Ref can be forwarded to child components through forwardRef;

The child component takes the ref created in the parent component and binds it to a certain element of its own;

The element bound to the ref in the child component can be obtained from the parent component.

import React, { memo, useRef,forwardRef } from 'react'
const HelloWorld = memo(forwardRef((props, ref) => {
  return (
    <input type="text" ref={ref} />
  )
}))
const App = memo(() => {
  const inputRef = useRef()
  function getInputDom() {
    // Get the input element in the child component    ()
    // Operate DOM    ()
  }
  return (
    <div>
      <HelloWorld ref={inputRef}/>
      <button onClick={getInputDom}>SubcomponentsinputGet focus</button>
    </div>
  )
})
export default App

There is no problem with forwardRef's approach itself, but we directly expose the DOM of the child component to the parent component:

The problems directly exposed to the parent component are uncontrollable in some situations;

The parent component can perform any operations after getting the DOM;

However, in fact, in the above case, we just want the parent component to operate the focus, and others don't want it to operate at will

For example, the operation of modifying the content of an element = "aaa"Wait, we hope to limit its operation;

UseImperativeHandle to expose fixed operations (restrict operations):

useImperativeHandle requires two parameters to be passed:

  • Parameter 1: Pass in a ref
  • Parameter 2: Pass in a callback function, requiring the callback function to return an object, the object will be bound to the current property of the passed ref

Through the useImperativeHandle's Hook, the object returned by the second parameter of useImperativeHandle is bound together; so in the parent component, when using , the object returned by parameter two is actually used;

For example, in the following code, a method focus is exposed in the child component through useImperativeHandle

const HelloWorld = memo(forwardRef((props, ref) => {
  // Process the ref passed in the parent component in the child component through useImperativeHandle  useImperativeHandle(ref, () => {
    return {
      focus() {
        ("focus call")
      }
    }
  })

  return (
    <input type="text" ref={ref} />
  )
}))

Then in the App parent component, it is essentially the object returned by parameter two.

const App = memo(() => {
  const inputRef = useRef()
  function getInputDom() {
    // The object obtained is also the return value of parameter two    ()
    // In essence, the focus method in the object returned by parameter two is called    ()
  }
  return (
    <div>
      <HelloWorld ref={inputRef}/>
      <button onClick={getInputDom}>SubcomponentsinputGet focus</button>
    </div>
  )
})

But we don't want to print a sentence as simply as in the above code, but want to really get the focus

Then we can redefine a ref object inside the child component, and then expose the operation we want to expose.

For example, in the following code, we only expose the operation of obtaining focus, which will become safer and more controllable; what function we want to use externally is entirely determined by the internal subcomponents

import React, { memo, useRef,forwardRef, useImperativeHandle } from 'react'
const HelloWorld = memo(forwardRef((props, ref) => {
  // Redefine a ref object inside the child component  const inputRef = useRef()
  // Process the ref passed in the parent component in the child component through useImperativeHandle  useImperativeHandle(ref, () => {
    return {
      focus() {
        ()
      }
    }
  })
  return (
    // Bind the ref object defined inside the component to the form    <input type="text" ref={inputRef} />
  )
}))
const App = memo(() => {
  const inputRef = useRef()
  function getInputDom() {
    ()
    // In essence, the object returned by parameter two is called    ()
  }
  return (
    <div>
      <HelloWorld ref={inputRef}/>
      <button onClick={getInputDom}>SubcomponentsinputGet focus</button>
    </div>
  )
})
export default App

This is the article about how React Hooks - useRef and useImperativeHandle is introduced here. For more information about React useRef and useImperativeHandle, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!