Back to All Articles
reactreact19performancefrontend

Exploring React 19: Mastering the New Activity Component and Automatic Memoization

Break down the latest React 19 updates, from the Activity component visibility management to automatic compiler memoization.

2026-10-28
Exploring React 19: Mastering the New Activity Component and Automatic Memoization

Let's look at what actually matters from the latest React updates: new primitives for managing visibility, smarter compiler memoization, and cleaner async event handling.

What you'll learn:

  • How to manage component visibility using the new primitive.
  • Writing side effects cleanly with useEffectEvent.
  • Leveraging React Compiler v1.0 for automatic memoization.
  • Handling DOM nodes cleanly with Fragment Refs.

Managing Component Visibility with

Toggling component visibility used to mean unmounting components and losing local state, or hiding them with CSS and burning CPU cycles. React 19 introduces the component to handle this properly.

It keeps the component tree alive while letting React know whether the content is visible or hidden. This lets background UI stay updated without running heavy layout calculations.

TSX
import { Activity } from 'react';

export function DashboardTab({ isActive }: { isActive: boolean }) {
  return (
    <Activity mode={isActive ? 'visible' : 'hidden'}>
      <HeavyLiveFeed />
    </Activity>
  );
}

Speed Note: Hidden activities preserve their local state and DOM structure, meaning instant toggling back to visible without a fresh mount cost.

Separating Logic from Effects with useEffectEvent

We have all fought with useEffect dependency arrays, pulling in functions just to satisfy the linter, only to trigger unwanted re-runs. useEffectEvent solves this by letting you define a non-reactive wrapper for logic inside an effect.

It captures the latest props and state without forcing the effect to re-execute when they change.

TSX
import { useState, useEffect, useEffectEvent } from 'react';

export function AnalyticsTracker({ pageId }: { pageId: string }) {
  const [clicks, setClicks] = useState(0);

  const onVisit = useEffectEvent((currentClicks: number) => {
    sendMetrics({ pageId, clicks: currentClicks });
  });

  useEffect(() => {
    // This effect only runs on mount/unmount, but always reads fresh clicks
    onVisit(clicks);
  }, [pageId]);

  return <button onClick={() => setClicks(c => c + 1)}>Click: {clicks}</button>;
}

Gotcha: useEffectEvent hooks can only be called from inside Effects, not during normal render passes.

Shipping Faster with React Compiler v1.0

Manual useMemo and useCallback clutter codebases and are easy to get wrong. React Compiler v1.0 automates memoization by analyzing your code at build time.

You write idiomatic React, and the compiler handles the reference stability for you.

TSX
// Before: Manual memoization clutter
import { useState, useMemo, useCallback } from 'react';

export function UserList({ users, filter }) {
  const filteredUsers = useMemo(() => {
    return users.filter(u => u.name.includes(filter));
  }, [users, filter]);

  const handleClick = useCallback((id) => {
    console.log(id);
  }, []);

  return <ItemTable items={filteredUsers} onItemClick={handleClick} />;
}

// After: React 19 Compiler handles this automatically
export function UserListOptimized({ users, filter }) {
  const filteredUsers = users.filter(u => u.name.includes(filter));
  const handleClick = (id) => console.log(id);

  return <ItemTable items={filteredUsers} onItemClick={handleClick} />;
}

Migration Tip: Run the official compiler linter rules first to spot any existing rule violations before enabling full automatic memoization.

Interacting with Fragment Refs

Fragments are great for avoiding extra wrapper divs in the DOM, but they historically made it impossible to attach a ref directly to the group of elements they wrapped. Fragment Refs fix this limitation.

You can now pass a ref straight to a Fragment to interact with its underlying DOM boundary nodes.

TSX
import { Fragment, useRef, useEffect } from 'react';

export function InlineActionGroup() {
  const fragmentRef = useRef<DocumentFragment>(null);

  useEffect(() => {
    console.log("Fragment mounted to DOM", fragmentRef.current);
  }, []);

  return (
    <Fragment ref={fragmentRef}>
      <span>First Item</span>
      <span>Second Item</span>
    </Fragment>
  );
}

Accessibility Note: Using fragments helps maintain clean semantic HTML landmarks (like lists or definition groups) without injecting unwanted layout styling wrappers.

Summary

React 19 brings practical tools that remove boilerplate and boost runtime performance. From managing view states to automatic compiler memoization, writing fast React apps is cleaner than ever.

Next Steps:

  • Upgrade your lint setup with the new React Compiler rules.
  • Identify heavy UI tabs in your app and test them with .
  • Clean up complex dependency arrays using useEffectEvent.