XState in React
You can use XState with React to:
- Coordinate local state
 - Manage global state performantly
 - Consume data from other hooks
 
We provide the official @xstate/react package to help you manage the integration. The package provides several hooks and helpers to get you started.
Installation​
Install the @xstate/react package using npm:
npm install xstate @xstate/react
useMachine hook​
The simplest way to get started with interpreting actors in React is useMachine. useMachine is a React hook that interprets the given machine and starts an actor that runs for the lifetime of the component.
import { createMachine } from 'xstate';
import { useMachine } from '@xstate/react';
const machine = createMachine({});
const Component = () => {
  const [
    // The current state of the actor
    state,
    // A function to send the machine events
    send,
    // The running actor - used for passing to `useActor`
    actor,
  ] = useMachine(machine);
  return null;
};
You can also pass machine options to the second argument of useMachine. These options will be kept up to date when the component re-renders, which means they can safely access variables inside the component’s scope:
const useLoggedInUserId = (): string => '123';
import { createMachine } from 'xstate';
import { useMachine } from '@xstate/react';
const machine = createMachine({
  entry: 'consoleLogUserId',
});
const Component = () => {
  const id = useLoggedInUserId();
  const [state, send] = useMachine(machine, {
    actions: {
      consoleLogUserId: () => {
        console.log(id);
      },
    },
  });
  return null;
};
useInterpret hook​
useMachine automatically subscribes to the current state of the machine, which means every state update will result in a re-render of the component that calls it. This re-rendering isn’t always desirable.
useInterpret allows you to interpret a machine without subscribing to its updates, which means that by default, it won’t cause any re-rendering in the component.
import { createMachine } from 'xstate';
import { useInterpret } from '@xstate/react';
const machine = createMachine({});
const Component = () => {
  const actor = useInterpret(machine);
  return null;
};
useInterpret accepts the same arguments as useMachine, and follows the same rules with options:
const useLoggedInUserId = (): string => '123';
import { createMachine } from 'xstate';
import { useInterpret } from '@xstate/react';
const machine = createMachine({
  entry: 'consoleLogUserId',
});
const Component = () => {
  const id = useLoggedInUserId();
  const actor = useInterpret(machine, {
    actions: {
      consoleLogUserId: () => {
        console.log(id);
      },
    },
  });
  return null;
};
useSelector​
You can use useSelector to subscribe to a machine created with useInterpret or interpret. useSelector gives you fine-grained control over when your components should re-render and is particularly valuable for good performance.
import { createMachine, StateFrom } from 'xstate';
import { useInterpret, useSelector } from '@xstate/react';
const machine = createMachine({
  initial: 'hovered',
  states: {
    hovered: {},
    notHovered: {},
  },
});
const selector = (state: StateFrom<typeof machine>) => state.matches('hovered');
const Component = () => {
  const actor = useInterpret(machine);
  const isHovered = useSelector(actor, selector);
  return null;
};
In the example above, the component will only re-render when the isHovered value changes from true to false.
Internally, useSelector compares the previous value (prev) and the next value (next) to determine whether a re-render is required. Strict equality is used for its default check: prev === next. If the check returns true, there will be no re-render.
You can customize the check by passing a compare function to useSelector:
import { createMachine, StateFrom } from 'xstate';
import { useInterpret, useSelector } from '@xstate/react';
const machine = createMachine({
  context: {
    numbers: [1, 2, 3],
  },
});
const getNumbers = (state: StateFrom<typeof machine>) => state.context.numbers;
const Component = () => {
  const actor = useInterpret(machine);
  const numbers = useSelector(actor, getNumbers, (prev, next) => {
    /**
     * Checks if 1,2,3 === 2,3,4
     */
    return prev.join() === next.join();
  });
  return null;
};
The compare function is needed in the example above because comparing two arrays by [] === [] would always result in a re-render.
useActor​
Use useActor if you want to subscribe to all updates to an actor from useInterpret:
import { createMachine, StateFrom } from 'xstate';
import { useInterpret, useActor } from '@xstate/react';
const machine = createMachine({
  initial: 'hovered',
  states: {
    hovered: {},
    notHovered: {},
  },
});
const Component = () => {
  const actor = useInterpret(machine);
  const [
    // The current state of the actor
    state,
    // A function to send the machine events
    send,
  ] = useActor(actor);
  const isHovered = state.matches('hovered');
  return null;
};
useActor subscribes to all state updates from the actor, providing a similar return type to useMachine.