Skip to content

Feature: Support React Compiler without requiring useMemo for machine factories #5426

@PaulRBerg

Description

@PaulRBerg

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):

// 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:

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions