Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
React Hook recipe from
import { useState, useCallback, useRef } from "react";
// Usage
function App() {
const [hoverRef, isHovered] = useHover();
return (
<div ref={hoverRef}>
{isHovered ? '😁' : '☹️'}
// 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];
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.