#5426·xstate

Feature: Support React Compiler without requiring useMemo for machine factories

Author: PaulRBergCreated Dec 9, 2025Updated Jan 1, 2026

Context

With React 19 and React Compiler, manual memoization via useMemo and useCallback is no longer recommended - the compiler automatically optimizes re-renders. However, @xstate/react's useActor hook compares logic.config by reference, which means machines created via factory functions (like setup().createMachine()) must still be wrapped in useMemo to prevent infinite re-render loops.

The Problem

When using a factory function to create a machine with dynamic config (e.g., passing wagmi config):

typescript
// This causes an infinite loop without useMemo
function MyComponent() {
  const config = useConfig();
  const machine = createMyMachine(config); // New reference each render
  const [state] = useActor(machine); // useActor detects "new" machine → setCurrent → re-render → loop
}

The workaround requires explicit memoization:

typescript
function MyComponent() {
  const config = useConfig();
  // Must memoize to prevent infinite loop
  const machine = useMemo(() => createMyMachine(config), [config]);
  const [state] = useActor(machine);
}

This works, but conflicts with React Compiler's philosophy of automatic memoization.

Proposed Solution

Consider one of these approaches:

  1. Deep equality check on machine config - Instead of reference equality on logic.config, use a deep comparison or hash of the relevant config properties.

  2. Stable machine identity hook - Provide a useStableMachine or similar that handles the memoization internally based on a user-provided dependency array.

  3. Document React Compiler compatibility - If this is intentional behavior, clearly document that useMemo is still required for factory-created machines even with React Compiler.

Environment

  • XState v5
  • @xstate/react
  • React 19 with React Compiler

Related Issues

  • #1101 - "Allow useMachine to accept a new machine between renders" (closed 2020)
  • #913 - "Why useConstant?" (closed 2019)