Skip to content

Instantly share code, notes, and snippets.

@silvio2402
Last active June 23, 2023 13:36
Show Gist options
  • Save silvio2402/20437df942059d0740e069525ecca32f to your computer and use it in GitHub Desktop.
Save silvio2402/20437df942059d0740e069525ecca32f to your computer and use it in GitHub Desktop.
React Ref Factory
import { useRef, Ref } from 'react'
import { refFactory } from './refFactory'
const ExampleButton = (props: { ref: Ref<HTMLButtonElement> }) => {
const { ref: refFromProps } = props
const refHook = useRef<HTMLButtonElement | null>(null)
const refCallback = (element: HTMLButtonElement) => {
console.log('Ref Callback', element)
}
// Works with any Refs!
return (
<button
ref={refFactory<HTMLButtonElement>()
.addRef(refFromProps)
.addRef(refHook)
.addRef(refCallback)}
>
Hello
</button>
)
}
export default ExampleButton
import { RefCallback, RefObject } from 'react'
type Mutable<T> = {
-readonly [P in keyof T]: T[P]
}
type MutableRef<T> = RefCallback<T> | Mutable<RefObject<T>> | null
export interface RefFactory<T extends HTMLElement> {
(element: T): void
addRef: (ref: MutableRef<T>) => RefFactory<T>
}
export const refFactory = <T extends HTMLElement>(): RefFactory<T> => {
const refs: MutableRef<T>[] = []
let refFactory: RefFactory<T> = ((element: T) => {
refs.forEach((ref) => {
if (typeof ref === 'function') {
ref(element)
} else if (ref) {
ref.current = element
}
})
}) as RefFactory<T>
refFactory.addRef = (ref) => {
if (ref) {
refs.push(ref)
}
return refFactory
}
return refFactory
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment