An open API service indexing awesome lists of open source software.

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.

Awesome Lists containing this project

README

          

[![Build Status](https://travis-ci.com/carloslfu/use-machine.svg?branch=master)](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)
```