React 19.2: Activity and useEffectEvent

By

Published Updated 1 min read

React 19.2 (October 2025) adds two features that fix long-standing annoyances: <Activity> for preserving UI state, and useEffectEvent for effects that read fresh values.

Activity: hide without losing state

Conditional rendering unmounts a component and throws away its state. <Activity> has a hidden mode: the UI is hidden, its effects are unmounted and updates are deprioritized, but state (form inputs, scroll position) is kept.

TypeScript / React
import { Activity, useState } from 'react';


export function Tabs() {
  const [tab, setTab] = useState<'draft' | 'preview'>('draft');


  return (
    <>
      <button onClick={() => setTab('draft')}>Draft</button>
      <button onClick={() => setTab('preview')}>Preview</button>


      <Activity mode={tab === 'draft' ? 'visible' : 'hidden'}>
        <Editor />
      </Activity>
      <Activity mode={tab === 'preview' ? 'visible' : 'hidden'}>
        <Preview />
      </Activity>
    </>
  );
}

Switching back to the draft keeps what the user typed. It is also useful for pre-rendering the next screen at low priority.

useEffectEvent: read the latest value without re-running

A common bug: an effect needs the latest theme for a notification, but adding it to the dependency array reconnects the chat.

TypeScript / React
import { useEffect, useEffectEvent } from 'react';


function ChatRoom({ roomId, theme }: { roomId: string; theme: string }) {
  const onConnected = useEffectEvent(() => {
    showNotification('Connected!', theme); // always the latest theme
  });


  useEffect(() => {
    const connection = createConnection(roomId);
    connection.on('connected', onConnected);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]); // theme is not a dependency
}

Rules: call an Effect Event only from inside effects, and never put it in a dependency array. The updated eslint-plugin-react-hooks enforces this.

Upgrade notes

Keep React and react-dom on the latest 19.2 patch release. Security fixes have shipped in the 19.x line, so do not pin to old patches.

Sources and further reading