Without going too much into the reasons why you'd want to do this, the code above has a simple problem.
The second argument expected by addEventListener
is a function that is supposed to be called when a given event gets triggered. Your code doesn't do that but instead it does this (after expanding it into a more readable form):
const animationStartListener = setIsAnimating(true);
ref?.current.addEventListener('animationstart', animationStartListener);
const animationEndListener = setIsAnimating(false);
ref?.current.addEventListener('animationend', animationEndListener);
For your code to work correctly you'd have to wrap the call to setIsAnimating(true)
in a function, and pass that function as an argument to the addEventListener
:
const animationStartListener = () => setIsAnimating(true);
ref?.current.addEventListener('animationstart', animationStartListener);
const animationEndListener = () => setIsAnimating(false);
ref?.current.addEventListener('animationend', animationEndListener);
or, using shorter syntax:
ref?.current.addEventListener('animationstart', () => setIsAnimating(true));
ref?.current.addEventListener('animationend', () => setIsAnimating(false));
Another thing to remember is that when you're removing a listener, you have to pass the same reference to the function as was passed to the addEventListener
. The correct way to do this in React using React Hooks is by the use of useCallback
hook:
function useIsAnimating(ref) {
const [isAnimating, setIsAnimating] = React.useState(false);
const handleAnimationStart = useCallback(
() => setIsAnimating(true),
[setIsAnimating],
);
const handleAnimationEnd = useCallback(
() => setIsAnimating(false),
[setIsAnimating],
);
useEffect(() => {
ref?.current.addEventListener('animationstart', handleAnimationStart);
ref?.current.addEventListener('animationend', handleAnimationEnd);
return () => {
ref?.current.removeEventListener('animationstart', handleAnimationStart);
ref?.current.removeEventListener('animationend', handleAnimationEnd);
};
}, [ref, handleAnimationStart, handleAnimationEnd]);
return isAnimating;
}
Hope that helps you with your problem (and I didn't make any spelling mistakes here).