https://github.com/carloslfu/use-machine
React Hook for using Statecharts powered by XState. use-machine.
https://github.com/carloslfu/use-machine
react react-hook state-machine state-management statecharts use-machine xstate
Last synced: 11 months ago
JSON representation
React Hook for using Statecharts powered by XState. use-machine.
- Host: GitHub
- URL: https://github.com/carloslfu/use-machine
- Owner: carloslfu
- License: mit
- Created: 2018-11-04T15:56:24.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2023-01-03T16:36:12.000Z (about 3 years ago)
- Last Synced: 2025-03-29T21:05:43.359Z (11 months ago)
- Topics: react, react-hook, state-machine, state-management, statecharts, use-machine, xstate
- Language: TypeScript
- Homepage:
- Size: 778 KB
- Stars: 226
- Watchers: 5
- Forks: 12
- Open Issues: 15
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-list - use-machine - machine. | carloslfu | 229 | (TypeScript)
README
[](https://travis-ci.com/carloslfu/use-machine)
# use-machine
Use Statecharts in React powered by XState, using the `useMachine` hook. This is a minimalistic implementation (just 30 lines) that integrates React and XState.
Install it with: `npm i use-machine`
See --> [the live example here!](https://codesandbox.io/s/5z0820jlyk).
Let's build something with it:
```javascript
import React, { useContext } from 'react'
import ReactDOM from 'react-dom'
import { assign } from 'xstate/lib/actions'
import { useMachine } from 'use-machine'
const incAction = assign(context => ({ counter: context.counter + 1 }))
const machineConfig = {
initial: 'Off',
context: {
counter: 0
},
states: {
Off: { on: { Tick: { target: 'On', actions: [incAction, 'sideEffect'] } } },
On: { on: { Tick: { target: 'Off', actions: incAction } } }
}
}
const MachineContext = React.createContext()
function App() {
const machine = useMachine(machineConfig, {
actions: {
sideEffect: () => console.log('sideEffect')
}
})
function sendTick() {
machine.send('Tick')
}
return (
{machine.state.matches('Off') ? 'Off' : 'On'}
Tick
Pressed: {machine.context.counter} times
)
}
function Child() {
const machine = useContext(MachineContext)
return (
Child state: {machine.state.matches('Off') ? 'Off' : 'On'}
Child count: {machine.context.counter}
)
}
function OtherChild() {
const machine = useContext(MachineContext)
function sendTick() {
machine.send('Tick')
}
return (
OtherChild state: {machine.state.matches('Off') ? 'Off' : 'On'}
OtherChild count: {machine.context.counter}
Tick 2
)
}
const rootElement = document.getElementById('root')
ReactDOM.render(, rootElement)
```
## TypeScript
This library is written in TypeScript, and XState too, so we have excellent support for types.
Example:
```typescript
import React, { useContext } from 'react'
import ReactDOM from 'react-dom'
import { MachineConfig } from 'xstate'
import { assign } from 'xstate/lib/actions'
import { useMachine, TCreateContext } from './use-machine'
type TContext = {
counter: number
}
type TSchema = {
states: {
Off: {},
On: {}
}
}
type TEvent = {
type: 'Tick'
}
const incAction = assign(context => ({ counter: context.counter + 1 }))
const machineConfig: MachineConfig = {
initial: 'Off',
context: {
counter: 0
},
states: {
Off: { on: { Tick: { target: 'On', actions: [incAction, 'sideEffect'] } } },
On: { on: { Tick: { target: 'Off', actions: incAction } } }
}
}
type TMachine = TCreateContext
const MachineContext = React.createContext({} as TMachine)
function App() {
const machine = useMachine(machineConfig, {
actions: {
sideEffect: () => console.log('sideEffect')
}
})
function sendTick() {
machine.send('Tick')
}
return (
{machine.state.matches('Off') ? 'Off' : 'On'}
Tick
Pressed: {machine.context.counter} times
)
}
function Child() {
const machine = useContext(MachineContext)
return (
Child state: {machine.state.matches('Off') ? 'Off' : 'On'}
Child count: {machine.context.counter}
)
}
function OtherChild() {
const machine = useContext(MachineContext)
function sendTick() {
machine.send('Tick')
}
return (
OtherChild state: {machine.state.matches('Off') ? 'Off' : 'On'}
OtherChild count: {machine.context.counter}
Tick 2
)
}
const rootElement = document.getElementById('root')
ReactDOM.render(, rootElement)
```