Skip to content

Instantly share code, notes, and snippets.

@segunadebayo
Created October 6, 2021 11:22
Show Gist options
  • Save segunadebayo/1a36e0f1df1029a1017cb519f61d5afd to your computer and use it in GitHub Desktop.
Save segunadebayo/1a36e0f1df1029a1017cb519f61d5afd to your computer and use it in GitHub Desktop.
use-effect-ref
import {useRef, useCallback} from 'react';
export type EffectRef<E extends HTMLElement = HTMLElement> = (element: E | null) => void;
export type RefCallback<E extends HTMLElement = HTMLElement> = (element: E) => (() => void) | void;
// eslint-disable-next-line @typescript-eslint/no-empty-function
const noop = () => {};
export function useEffectRef<E extends HTMLElement = HTMLElement>(callback: RefCallback<E>): EffectRef<E> {
const disposeRef = useRef<(() => void)>(noop);
const effect = useCallback(
(element: E | null) => {
disposeRef.current();
// To ensure every dispose function is called only once.
disposeRef.current = noop;
if (element) {
const dispose = callback(element);
if (typeof dispose === 'function') {
disposeRef.current = dispose;
}
// Have an extra type check to work with javascript.
else if (dispose !== undefined) {
// eslint-disable-next-line no-console
console.warn('Effect ref callback must return undefined or a dispose function');
}
}
},
[callback]
);
return effect;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment