Skip to content

Instantly share code, notes, and snippets.

@kyle-west
Last active March 4, 2025 23:48
Show Gist options
  • Save kyle-west/ce30ece81ea94375b5d72a0b8296eb02 to your computer and use it in GitHub Desktop.
Save kyle-west/ce30ece81ea94375b5d72a0b8296eb02 to your computer and use it in GitHub Desktop.
This is how I like to use useImperativeHandle to "sync" or compose refs in React
import React, { useImperativeHandle, useRef, forwardRef, useCallback, useEffect } from 'react'
export const Component = forwardRef(({ callbackRef }, externalRef) => {
const internalRef = useRef()
// use imperative handle lets you "sync" any number of external refs with the value of the internalRef
useImperativeHandle(externalRef, () => internalRef.current)
useImperativeHandle(callbackRef, () => internalRef.current)
useEffect(() => {
console.log("This is the internalRef", internalRef)
}, [])
// for this to work, you have to bind the internalRef to the actual dom
return <div ref={internalRef}>This actually works</div>
})
// Usage
export default function App () {
const externalRef = useRef()
// Even works with callback refs
const callbackRef = useCallback((node) => console.log("This is the callback ref", node), [])
useEffect(() => {
console.log("This is the externalRef", externalRef)
}, [])
return <Component ref={externalRef} callbackRef={callbackRef}/>
}
@kyle-west
Copy link
Author

kyle-west commented Mar 26, 2021

Console output:

This is the callback ref <div>​This actually works​</div>​
This is the internalRef {current: div}
This is the externalRef {current: div}

@ryanflorence
Copy link

Amazing

@kyle-west
Copy link
Author

Credit to @matthewmatician who originally showed me this method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment