React Hook for using Statecharts powered by XState.
Switch branches/tags
Nothing to show
Clone or download
Latest commit d6a6c15 Nov 13, 2018
Permalink
Failed to load latest commit information.
src Support use-machine in React Context Nov 13, 2018
.editorconfig initial commit Nov 4, 2018
.gitignore initial commit Nov 4, 2018
README.md initial commit Nov 4, 2018
package-lock.json initial commit Nov 4, 2018
package.json release v0.4.1 Nov 14, 2018
tsconfig.json initial commit Nov 4, 2018

README.md

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

Example use, try it in codesandbox:

import React, { useContext } from 'react'
import ReactDOM from 'react-dom'
import { matchesState } from 'xstate'
import { assign } from 'xstate/lib/actions'
import { useMachine } from 'use-machine'

const incAction = assign(exState => ({ counter: exState.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 (
    <div className="App">
      <span
        style={{
          backgroundColor: matchesState(machine.state, 'Off') ? 'red' : 'yellow'
        }}
      >
        {matchesState(machine.state, 'Off') ? 'Off' : 'On'}
      </span>
      <button onClick={sendTick}>Tick</button>
      Pressed: {machine.exState.counter} times
      <MachineContext.Provider value={machine}>
        <div className="childs">
          <Child />
        </div>
      </MachineContext.Provider>
    </div>
  )
}

function Child() {
  const machine = useContext(MachineContext)
  return (
    <div>
      <div>
        Child state: {matchesState(machine.state, 'Off') ? 'Off' : 'On'}
      </div>
      <div>Child count: {machine.exState.counter}</div>
      <OtherChild />
    </div>
  )
}

function OtherChild() {
  const machine = useContext(MachineContext)

  function sendTick() {
    machine.send('Tick')
  }
  return (
    <div>
      <div>
        OtherChild state: {matchesState(machine.state, 'Off') ? 'Off' : 'On'}
      </div>
      <div>OtherChild count: {machine.exState.counter}</div>
      <button onClick={sendTick}>Tick 2</button>
    </div>
  )
}

const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)