Enable Dark Mode!
how-to-use-useeffectevent-in-react-19.jpg
By: Alan Joy

How to Use useEffectEvent in React 19

Technical React

React 19 introduces a powerful new hook called useEffectEvent, designed to make effects more predictable and easier to manage. If you’ve ever run into the “stale closure” problem or written overly complex dependency arrays, this hook is for you.

The Problem with useEffect

Let’s start with a classic problem every React developer has faced:

import { useEffect, useState } from "react";
function Timer() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    const interval = setInterval(() => {
      console.log("Count:", count);
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(interval);
  }, []); // Problem: `count` is stale!
  return <p>Count: {count}</p>;
}

At first glance, this looks fine. But since count is not included in the dependency array, the closure inside setInterval always references the initial value of count (0).

If you add count to the dependencies, the effect will re-run every second, recreating a new interval repeatedly—leading to multiple intervals running at once.

This issue happens because functions in React capture values from when they were created.

And that’s exactly the problem useEffectEvent solves.

What is useEffectEvent?

useEffectEvent is a new React 19 hook that lets you define event functions inside effects that can always access the latest props or state, without causing the effect to re-run.

It gives you a stable reference to a function that always reads the most current data.

Using useEffectEvent: Example

Here’s how we can fix the Timer component using useEffectEvent:

import { useState, useEffect, useEffectEvent } from "react";
function Timer() {
  const [count, setCount] = useState(0);
  // Define a stable event that always uses the latest state
  const onTick = useEffectEvent(() => {
    console.log("Count:", count);
    setCount(count + 1);
  });
  useEffect(() => {
    const interval = setInterval(() => {
      onTick();
    }, 1000);
    return () => clearInterval(interval);
  }, [onTick]); // stable reference, effect runs only once
  return <p>Count: {count}</p>;
}

What changed:

  • The useEffect itself still runs once.
  • The onTick event always has access to the latest count.
  • We’ve eliminated stale closures without adding dependencies.

Practical Example — Handling Window Events

Let’s see a practical case where useEffectEvent shines — handling a resize event:

import { useState, useEffect, useEffectEvent } from "react";
function WindowTracker() {
  const [width, setWidth] = useState(window.innerWidth);
  const handleResize = useEffectEvent(() => {
    setWidth(window.innerWidth);
    console.log("Resized:", width); // always latest width
  });
  useEffect(() => {
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, [handleResize]);
  return <p>Window width: {width}px</p>;
}

Here’s what’s happening:

  • The handleResize function always reads the latest width.
  • The useEffect doesn’t re-run unnecessarily.
  • Your event listener stays stable and accurate — even after state changes.

When to Use useEffectEvent

Use useEffectEvent when:

  • You’re defining a function inside an effect that reads the latest props or state.
  • You want to avoid adding too many dependencies in your useEffect.
  • You need stable event callbacks inside effects like setInterval, setTimeout, or event listeners.

Avoid using it when:

  • You’re calling it during render.
  • You need a memoized callback for UI props — use useCallback instead.

Best Practices

  • Keep logic small and specific inside useEffectEvent.
  • Use it only inside effects or event handlers — not render.
  • Don’t replace useCallback with it — they solve different problems.
  • If your effect uses async operations or subscriptions, useEffectEvent makes cleanup easier and safer.

To read more about What are the Key Features in React 19, refer to our blog What are the Key Features in React 19.


If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message