When I was hitting my head on the wall trying to figure out ways and patterns on how to handle local and global state using React Hooks, I saw many engineers are using the useFlasher
hook.
import { useRef, useEffect } from 'react';
export const useFlasher = () => {
const ref = useRef<HTMLElement>(null);
useEffect(() => {
if (!ref.current) return;
ref.current.setAttribute(
'style',
'box-shadow: 0 0 4px 1px orange; transition: box-shadow 400ms ease-out;',
);
setTimeout(() => {
if (!ref.current) return;
ref.current.setAttribute('style', '');
}, 300);
});
return ref;
};
Its purpose it to flash an element when it renders so to see when a component re-renders on state changes. It applies to a component ref
so to get the HTMLElement
and it has an effect that sets a box-shadow
style to that element and sets-up a timer timeout to clear the style after X milliseconds. Very clever and practical way to visually check for component re-renders when using hooks.
One minor mistake that this hook effect has is that it does not clear the timer timeout on burst calls. For example, if I set the useFlasher
to a component that updates on user text input, the flash effect will execute per less than 50 milliseconds and we won’t have an accurate visual effect. Small thing but why not fix it…
import { useRef, useEffect } from 'react';
export const useFlasher = () => {
const ref = useRef<HTMLElement>(null);
useEffect(() => {
if (!ref.current) return;
ref.current.setAttribute(
'style',
'box-shadow: 0 0 4px 1px orange; transition: box-shadow 400ms ease-out;',
);
const timer = setTimeout(() => {
if (!ref.current) return;
ref.current.setAttribute("style", "");
}, 300);
return () => clearTimeout(timer);
});
return ref;
};