Skip to content

Instantly share code, notes, and snippets.

@thebuilder
Last active January 16, 2024 13:50
Show Gist options
  • Save thebuilder/fb07c989093d4a82811625de361884e7 to your computer and use it in GitHub Desktop.
Save thebuilder/fb07c989093d4a82811625de361884e7 to your computer and use it in GitHub Desktop.
Hook with ref callback
import React, {useCallback, useRef} from 'react'
function useHookWithRefCallback() {
const ref = useRef(null)
const setRef = useCallback(node => {
if (ref.current) {
// Make sure to cleanup any events/references added to the last instance
}
if (node) {
// Check if a node is actually passed. Otherwise node would be null.
// You can now do what you need to, addEventListeners, measure, etc.
}
// Save a reference to the node
ref.current = node
}, [])
return [setRef]
}
function Component() {
// In your component you'll still recieve a `ref`, but it
// will be a callback function instead of a Ref Object
const [ref] = useHookWithRefCallback()
return <div ref={ref}>Ref element</div>
}
@claytonrothschild
Copy link

Excellent gist!

If you return the ref itself, it would allow other components to potentially change the ref.current

@thebuilder, I'm trying to understand how this would happen. Are you able to describe this risk further with a quick example? Thank you.

@thebuilder
Copy link
Author

Setting .current doesn't trigger a rerender, so things might not work like you expect.

function Component() {
  // In your component you'll still recieve a `ref`, but it 
  // will be a callback function instead of a Ref Object
  const [ref] = useHookWithRef()
  
  ref.current = 'Not your div'

  return <div ref={ref}>Ref element</div>
}

@reorx
Copy link

reorx commented Jan 16, 2024

I'm wondering why you're returning [setRef] instead of setRef directly. Is there a specific reason for this?

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