# Getting Started
# Our first machine
Suppose we want to model a Promise (opens new window) as a state machine. First, install XState using NPM or Yarn:
npm install xstate --save
If you're using VSCode, you should install our VSCode Extension (opens new window) to allow you to visualize the machine you're building as you go.
Then, in your project, import createMachine
, which is a function that creates a state machine.
import { createMachine } from 'xstate';
const promiseMachine = createMachine(/* ... */);
We'll pass the machine configuration to createMachine
. We'll need to provide the:
id
- to identify the machineinitial
- to specify the initial state node this machine should be instates
- to define each of the child states:
import { createMachine } from 'xstate';
const promiseMachine = createMachine({
id: 'promise',
initial: 'pending',
states: {
pending: {},
resolved: {},
rejected: {}
}
});
Then, we need to add transitions to the state nodes.
import { createMachine } from 'xstate';
const promiseMachine = createMachine({
id: 'promise',
initial: 'pending',
states: {
pending: {
on: {
RESOLVE: { target: 'resolved' },
REJECT: { target: 'rejected' }
}
},
resolved: {},
rejected: {}
}
});
We'll also need to mark the resolved
and rejected
state nodes as final state nodes since the promise machine terminates running once it reaches those states:
import { createMachine } from 'xstate';
const promiseMachine = createMachine({
id: 'promise',
initial: 'pending',
states: {
pending: {
on: {
RESOLVE: { target: 'resolved' },
REJECT: { target: 'rejected' }
}
},
resolved: {
type: 'final'
},
rejected: {
type: 'final'
}
}
});
Our machine is now ready to be visualized. You can copy/paste the code above and visualize it on Stately Viz (opens new window). Here's how it'll look:
# Running our machine
How we run our machine depends on where we're planning to use it.
# In Node/Vanilla JS
To interpret the machine and make it run, we need to add an interpreter. This creates a service:
import { createMachine, interpret } from 'xstate';
const promiseMachine = createMachine({
/* ... */
});
const promiseService = interpret(promiseMachine).onTransition((state) =>
console.log(state.value)
);
// Start the service
promiseService.start();
// => 'pending'
promiseService.send({ type: 'RESOLVE' });
// => 'resolved'
# In React
If we wanted to use our machine inside a React component, we could use the useMachine hook:
You'll need to install
@xstate/react
import { useMachine } from '@xstate/react';
const Component = () => {
const [state, send] = useMachine(promiseMachine);
return (
<div>
{/** You can listen to what state the service is in */}
{state.matches('pending') && <p>Loading...</p>}
{state.matches('rejected') && <p>Promise Rejected</p>}
{state.matches('resolved') && <p>Promise Resolved</p>}
<div>
{/** You can send events to the running service */}
<button onClick={() => send('RESOLVE')}>Resolve</button>
<button onClick={() => send('REJECT')}>Reject</button>
</div>
</div>
);
};