useEffectEvent Hook - React's new hook


posted by Akash Sarki on 30 December 2025
If you’ve spent any time with React, you know the "Dependency Array Dance." You write a useEffect, the linter screams at you to add a variable to the dependencies, you add it, and suddenly your effect is running way too often. You’re caught between stale closures (old data) and infinite loops (too much reactivity).
In React 19.2, we finally have a built-in escape hatch: useEffectEvent.
The Core Conflict: Reactive vs. Non-Reactive
Inside a standard useEffect, every variable is treated as reactive. If it changes, the effect synchronizes. But in the real world, logic is often a mix:
1. The Trigger (Reactive): "I want this code to run because the Room ID changed."
2. The Context (Non-Reactive): "When that code runs, I need to know what the current Theme is, but I don't want to restart everything just because the Theme changed."
The Solution: A "Read-Only" Window
useEffectEvent allows you to wrap logic in a special function that always sees the latest state and props but never triggers a re-sync of your effect.
Think of it like a "teleportation" hook. It takes a piece of code, moves it outside the reactive lifecycle, but keeps it connected to the latest data.
Example:
// 1. Define the "Event" (The non-reactive part)
const onMessage = useEffectEvent((msg) => {
showNotification(msg, theme); // Always gets the latest theme!
});
// 2. Define the "Effect" (The reactive part)
useEffect(() => {
const socket = connect(roomId);
socket.on('message', onMessage);
return () => socket.disconnect();
}, [roomId]); // ✅ Only reconnects if roomId changes!The Rules of the Road
Because useEffectEvent handles "non-reactive" logic, React places strict guardrails on it to prevent bugs:
- Internal Use Only: You can only call an Effect Event from inside an actual useEffect. You can't call it in your component body or in an onClick.
- Stability Guaranteed: The function identity never changes. You don't need to (and shouldn't) put it in dependency arrays.
- No Rendering: Since it's for side effects, you can't use it to calculate values used directly in your JSX.
Summary: When to Reach for It
You should use useEffectEvent whenever you find yourself fighting the dependency array. If you are adding a variable to useEffect just to satisfy the linter—but you don't actually want the effect to restart when that variable changes—that is your signal to use useEffectEvent.
It’s the final piece of the puzzle that makes useEffect feel like a tool you control, rather than a tool that controls you.
Another React 19 feature you should know is the new Activity Component.
Click here to know more.





