Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
React Hook recipe from https://usehooks.com
import { useState, useCallback, useRef } from "react";
// Usage
function App() {
const [hoverRef, isHovered] = useHover();
return (
<div ref={hoverRef}>
{isHovered ? '😁' : '☹️'}
</div>
);
}
// Hook
function useHover() {
const [value, setValue] = useState(false);
// Wrap in useCallback so we can use in dependencies below
const handleMouseOver = useCallback(() => setValue(true), []);
const handleMouseOut = useCallback(() => setValue(false), []);
// Keep track of the last node passed to callbackRef
// so we can remove its event listeners.
const ref = useRef();
// Use a callback ref instead of useEffect so that event listeners
// get changed in the case that the returned ref gets added to
// a different element later. With useEffect, changes to ref.current
// wouldn't cause a rerender and thus the effect would run again.
const callbackRef = useCallback(
node => {
if (ref.current) {
ref.current.removeEventListener("mouseover", handleMouseOver);
ref.current.removeEventListener("mouseout", handleMouseOut);
}
ref.current = node;
if (ref.current) {
ref.current.addEventListener("mouseover", handleMouseOver);
ref.current.addEventListener("mouseout", handleMouseOut);
}
},
[handleMouseOver, handleMouseOut]
);
return [callbackRef, value];
}
@abirmingham

This comment has been minimized.

Copy link

abirmingham commented Nov 22, 2019

Just curious... will useCallback(null) be called when the App is unmounted? Otherwise it appears that there is a memory leak here, where removeEventListener would be called on <div> rebinds but not App unmount.

EDIT: It does appear that useCallback(null) is called, which means that my concerns about the memory leak were unfounded.

@therealparmesh

This comment has been minimized.

Copy link

therealparmesh commented Jan 30, 2020

Should you use useEffect to handle subscribing/unsubscribing logic in a manner that is guaranteed to be safe by React? See https://github.com/therealparmesh/use-hovering.

@mbelsky

This comment has been minimized.

Copy link

mbelsky commented Feb 14, 2020

Thanks for sharing! I've typed this hook with Typescript, you may find it here: https://gist.github.com/mbelsky/72c1117a63489daf8e6067049d4532d0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.