# react-xstate-js

> A React interpreter for XState.

Latest version **2.2.0** (published 2019-03-10) · MIT license · 0 weekly downloads

> **Deprecated.** This package is deprecated.

## Install

```sh
npm install react-xstate-js
pnpm add react-xstate-js
yarn add react-xstate-js
bun add react-xstate-js
```

## Health

**Score 10/100 (F)** — status: deprecated.

Negative: deprecated.

## Facts

| | |
|---|---|
| Version | 2.2.0 |
| Published | 2019-03-10 |
| First published | 2018-10-16 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=6.0.0 |
| Dependencies | 2 |
| Unpacked size | 1.4 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Brad Woods |
| Maintainers | bradwoods.io |
| Keywords | react, xstate, statechart, state machine, finite state machine, finite automata |

## Links

- npm: https://www.npmjs.com/package/react-xstate-js
- Homepage: https://github.com/bradwoods/react-xstate-js
- npm.io page: https://npm.io/package/react-xstate-js

## Dependencies (2)

- [react](https://npm.io/package/react.md) ^16.6.0
- [xstate](https://npm.io/package/xstate.md) ^4.2.3

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 2.2.0 (latest) — 2019-03-10
- 2.1.0 — 2019-01-02
- 2.0.4 — 2018-12-29
- 2.0.3 — 2018-12-29
- 2.0.2 — 2018-12-23
- 2.0.1 — 2018-12-13
- 1.1.4 — 2018-12-10
- 2.0.0 — 2018-11-18
- 1.2.0 — 2018-10-31
- 1.1.3 — 2018-10-30
- 1.1.1 — 2018-10-29
- 1.1.0 — 2018-10-28
- 1.0.7 — 2018-10-21
- 1.0.6 — 2018-10-21
- 1.0.5 — 2018-10-21
- … 5 more at https://npm.io/package/react-xstate-js/versions

## README

# react-xstate-js
A React interpreter for [xstate](https://github.com/davidkpiano/xstate) that uses renderProps.

# Installation
```bash
yarn add react-xstate-js
```
or
```bash
npm i react-xstate-js -S
```

# Using
## Example 1 - reading & changing state
```jsx
import React from 'react';
import { Machine } from 'react-xstate-js';

const myMachineConfig = {
  key: 'example1',
  initial: 'step1',
  states: {
    step1: {
      on: {
        NEXT: 'step2',
      },
    },
    step2: {
      on: {
        PREVIOUS: 'step1',
        NEXT: 'step3',
      },
    },
    step3: {
      on: {
        PREVIOUS: 'step2',
      },
    },
  },
};

const MyComponent = () => (
  <Machine config={myMachineConfig}>
    {({ service, state }) => (
    <>
      <button
        type="button"
        onClick={() => service.send({ type: 'PREVIOUS' })}
      >
        previous
      </button>
      <button
        type="button"
        onClick={() => service.send({ type: 'NEXT' })}
      >
        next
      </button>
      <p>
        state:
        {' '}
        {JSON.stringify(state.value)}
      </p>
    </>
    )}
  </Machine>
);
```

## Example 1 - TypeScript
```tsx
import React from 'react';
import { 
  MachineConfig, Machine, State, Interpreter
} from 'react-xstate-js'

interface MyStateSchema {
  states: {
    step1: {}
    step2: {}
    step3: {}
  }
}

type MyEvent = { type: 'NEXT' } 
  | { type: 'PREVIOUS' }

const myMachineConfig: MachineConfig<{}, MyStateSchema, MyEvent> = {
  key: 'example1',
  initial: 'step1',
  states: {
    step1: {
      on: {
        NEXT: 'step2',
      },
    },
    step2: {
      on: {
        PREVIOUS: 'step1',
        NEXT: 'step3',
      },
    },
    step3: {
      on: {
        PREVIOUS: 'step2',
      },
    },
  },
}

const MyComponent: React.SFC = () => (
  <Machine config={myMachineConfig}>
    {({ service, state }: { service: Interpreter<{}, MyStateSchema, MyEvent>, state: State<{}, MyEvent> }) => (
      <>
        <button
          type="button"
          onClick={() => service.send({ type: 'PREVIOUS' })}
        >
          previous
        </button>
        <button
          type="button"
          onClick={() => service.send({ type: 'NEXT' })}
        >
          next
        </button>
        <p>
          state:
          {' '}
          {JSON.stringify(state.value)}
        </p>
      </>
    )}
  </Machine>
)
```

## Example 2 - options (with actions)
```jsx
import React from 'react';
import { Machine } from 'react-xstate-js';

const myMachineConfig = {
  key: 'example2',
  initial: 'step1',
  states: {
    step1: {
      on: {
        NEXT: 'step2',
      },
    },
    step2: {
      onEntry: ['myAction'],
      on: {
        PREVIOUS: 'step1',
        NEXT: 'step3',
      },
    },
    step3: {
      on: {
        PREVIOUS: 'step2',
      },
    },
  },
};

const myMachineOptions = {
  actions: {
    myAction: () => {
      console.log('myAction fired');
    },
  },
};

const MyComponent = () => (
  <Machine
    config={myMachineConfig}
    options={myMachineOptions}
  >
    {({ service, state }) => (
    <>
      <button
        type="button"
        onClick={() => service.send({ type: 'PREVIOUS' })}
      >
        previous
      </button>
      <button
        type="button"
        onClick={() => service.send({ type: 'NEXT' })}
      >
        next
      </button>
      <p>
        state:
        {' '}
        {JSON.stringify(state.value)}
      </p>
    </>
    )}
  </Machine>
);
```

## Example 2 - TypeScript
```tsx
import React from 'react';
import {
  MachineConfig, MachineOptions, Machine, State, Interpreter
} from 'react-xstate-js'

interface MyStateSchema {
  states: {
    step1: {}
    step2: {}
    step3: {}
  }
}

type MyEvent = { type: 'NEXT' }
  | { type: 'PREVIOUS' }

const myMachineConfig: MachineConfig<{}, MyStateSchema, MyEvent> = {
  key: 'example1',
  initial: 'step1',
  states: {
    step1: {
      on: {
        NEXT: 'step2',
      },
    },
    step2: {
      onEntry: ['myAction'],
      on: {
        PREVIOUS: 'step1',
        NEXT: 'step3',
      },
    },
    step3: {
      on: {
        PREVIOUS: 'step2',
      },
    },
  },
}

const myMachineOptions: MachineOptions<{}, MyEvent> = {
  actions: {
    myAction: () => {
      console.log('myAction fired');
    },
  },
};

const MyComponent: React.SFC = () => (
  <Machine 
    config={myMachineConfig}
    options={myMachineOptions}
  >
    {({ service, state }: { service: Interpreter<{}, MyStateSchema, MyEvent>, state: State<{}, MyEvent> }) => (
      <>
        <button
          type="button"
          onClick={() => service.send({ type: 'PREVIOUS' })}
        >
          previous
        </button>
        <button
          type="button"
          onClick={() => service.send({ type: 'NEXT' })}
        >
          next
        </button>
        <p>
          state:
          {' '}
          {JSON.stringify(state.value)}
        </p>
      </>
    )}
  </Machine>
)
```

## Example 3 - context
```jsx
import React from 'react';
import { 
  Machine, assign 
} from 'react-xstate-js';

const myMachineConfig = {
  key: 'example3',
  context: {
    foo: '',
  },
  initial: 'step1',
  states: {
    step1: {
      on: {
        NEXT: 'step2',
      },
    },
    step2: {
      onEntry: ['myAction'],
      on: {
        PREVIOUS: 'step1',
        NEXT: 'step3',
      },
    },
    step3: {
      on: {
        PREVIOUS: 'step2',
      },
    },
  },
};

const myMachineOptions = {
  actions: {
    myAction: assign({ foo: () => 'bar' }),
  },
};

const MyComponent = () => (
  <Machine
    config={myMachineConfig}
    options={myMachineOptions}
  >
    {({ service, state }) => (
    <>
      <button
        type="button"
        onClick={() => service.send({ type: 'PREVIOUS' })}
      >
        previous
      </button>
      <button
        type="button"
        onClick={() => service.send({ type: 'NEXT' })}
      >
        next
      </button>
      <p>
        state:
        {' '}
        {JSON.stringify(state.value)}
      </p>
      <p>
        context:
        {' '}
        {JSON.stringify(state.context)}
      </p>
    </>
    )}
  </Machine>
);
```

## Example 3 - TypeScript
```tsx
import React from 'react';
import {
  MachineConfig, MachineOptions, Machine, State, Interpreter, assign
} from 'react-xstate-js'

interface MyContext {
  foo: string
}

interface MyStateSchema {
  states: {
    step1: {}
    step2: {}
    step3: {}
  }
}

type MyEvent = { type: 'NEXT' }
  | { type: 'PREVIOUS' }

const myMachineConfig: MachineConfig<MyContext, MyStateSchema, MyEvent> = {
  key: 'example1',
  context: {
    foo: '',
  },
  initial: 'step1',
  states: {
    step1: {
      on: {
        NEXT: 'step2',
      },
    },
    step2: {
      onEntry: ['myAction'],
      on: {
        PREVIOUS: 'step1',
        NEXT: 'step3',
      },
    },
    step3: {
      on: {
        PREVIOUS: 'step2',
      },
    },
  },
}

const myMachineOptions: MachineOptions<MyContext, MyEvent> = {
  actions: {
    myAction: assign({ foo: () => 'bar' }),
  },
};

const MyComponent: React.SFC = () => (
  <Machine
    config={myMachineConfig}
    options={myMachineOptions}
  >
    {({ service, state }: { service: Interpreter<MyContext, MyStateSchema, MyEvent>, state: State<MyContext, MyEvent> }) => (
      <>
        <button
          type="button"
          onClick={() => service.send({ type: 'PREVIOUS' })}
        >
          previous
        </button>
        <button
          type="button"
          onClick={() => service.send({ type: 'NEXT' })}
        >
          next
        </button>
        <p>
          state:
          {' '}
          {JSON.stringify(state.value)}
        </p>
        <p>
          context:
          {' '}
          {JSON.stringify(state.context)}
        </p>
      </>
    )}
  </Machine>
)
```

## Example 4 - persisting state
```jsx
import React from 'react';
import {
  Machine,
} from 'react-xstate-js'

const myMachineConfig = {
  key: 'example1',
  initial: 'step1',
  states: {
    step1: {
      on: {
        NEXT: 'step2',
      },
    },
    step2: {
      on: {
        PREVIOUS: 'step1',
        NEXT: 'step3',
      },
    },
    step3: {
      on: {
        PREVIOUS: 'step2',
      },
    },
  },
}

const mySavedJSONState = `{ "actions": [], "activities": {}, "meta": {}, "events": [], "value": "step3", "event": { "type": "NEXT" }, "historyValue": { "current": "step3", "states": {} }, "history": { "actions": [], "activities": {}, "meta": {}, "events": [], "value": "step2", "event": { "type": "NEXT" }, "historyValue": { "current": "step2", "states": {} }, "history": { "actions": [], "activities": {}, "meta": {}, "events": [], "value": "step1", "event": { "type": "xstate.init" } } } }`

const mySavedState = JSON.parse(mySavedJSONState)

const MyComponent = () => (
  <Machine 
    config={myMachineConfig}
    savedState={mySavedState}
  >
    {({ service, state }) => (
      <>
        <button
          type="button"
          onClick={() => service.send({ type: 'PREVIOUS' })}
        >
          previous
      </button>
        <button
          type="button"
          onClick={() => service.send({ type: 'NEXT' })}
        >
          next
      </button>
        <p>
          state:
          {' '}
          {JSON.stringify(state.value)}
        </p>
      </>
    )}
  </Machine>
)

export default MyComponent
```

## Example 4 - TypeScript
```tsx
import React from 'react';
import {
  MachineConfig, Machine, State, Interpreter
} from 'react-xstate-js'

interface MyStateSchema {
  states: {
    step1: {}
    step2: {}
    step3: {}
  }
}

type MyEvent = { type: 'NEXT' }
  | { type: 'PREVIOUS' }

const myMachineConfig: MachineConfig<{}, MyStateSchema, MyEvent> = {
  key: 'example1',
  initial: 'step1',
  states: {
    step1: {
      on: {
        NEXT: 'step2',
      },
    },
    step2: {
      on: {
        PREVIOUS: 'step1',
        NEXT: 'step3',
      },
    },
    step3: {
      on: {
        PREVIOUS: 'step2',
      },
    },
  },
}

const mySavedJSONState = `{ "actions": [], "activities": {}, "meta": {}, "events": [], "value": "step3", "event": { "type": "NEXT" }, "historyValue": { "current": "step3", "states": {} }, "history": { "actions": [], "activities": {}, "meta": {}, "events": [], "value": "step2", "event": { "type": "NEXT" }, "historyValue": { "current": "step2", "states": {} }, "history": { "actions": [], "activities": {}, "meta": {}, "events": [], "value": "step1", "event": { "type": "xstate.init" } } } }`

const mySavedState: State<{}, MyEvent> = JSON.parse(mySavedJSONState)

const MyComponent: React.SFC = () => (
  <Machine 
    config={myMachineConfig}
    savedState={mySavedState}
  >
    {({ service, state }: { service: Interpreter<{}, MyStateSchema, MyEvent>, state: State<{}, MyEvent> }) => (
      <>
        <button
          type="button"
          onClick={() => service.send({ type: 'PREVIOUS' })}
        >
          previous
      </button>
        <button
          type="button"
          onClick={() => service.send({ type: 'NEXT' })}
        >
          next
      </button>
        <p>
          state:
          {' '}
          {JSON.stringify(state.value)}
        </p>
      </>
    )}
  </Machine>
)

export default MyComponent
```

# API
## \<Machine \/\>
A [React](https://reactjs.org/) interpreter for [xstate](https://github.com/davidkpiano/xstate).
```jsx
<Machine
  config={...}
  options={...}
>
  {({ service, state }) => (
    ...
  )}
</Machine>
```

### Props
#### config: xstate [machine config](https://xstate.js.org/api/interfaces/machineconfig.html).
```js
const mmyMachineConfig = {
  key: 'example1',
  initial: 'step1',
  states: {
    step1: {
      on: {
        NEXT: 'step2',
      },
    },
    step2: {
      on: {
        PREVIOUS: 'step1',
        NEXT: 'step3',
      },
    },
    step3: {
      on: {
        PREVIOUS: 'step2',
      },
    },
  },
};
```

#### options: xstate [machine options](https://xstate.js.org/api/interfaces/machineoptions.html).
```js
const myMachineOptions = {
  actions: {
    myAction: () => {
      console.log('myAction fired');
    },
  },
};
```

#### savedState: xstate [State](https://xstate.js.org/api/classes/state.html).
```js
const savedState = {
  "actions": [],
  "activities": {},
  "meta": {},
  "events": [],
  "value": "step3",
  "event": {
    "type": "NEXT"
  },
  "historyValue": {
    "current": "step3",
    "states": {}
  },
  "history": {
    "actions": [],
    "activities": {},
    "meta": {},
    "events": [],
    "value": "step2",
    "event": {
      "type": "NEXT"
    },
    "historyValue": {
      "current": "step2",
      "states": {}
    },
    "history": {
      "actions": [],
      "activities": {},
      "meta": {},
      "events": [],
      "value": "step1",
      "event": {
        "type": "PREVIOUS"
      },
      "historyValue": {
        "current": "step1",
        "states": {}
      }
    }
  }
};
```

### Return
#### service: xstate [interpreter](https://xstate.js.org/docs/guides/interpretation.html).
```jsx
<Machine {...} >
  {({ service }) => (
    ...
  )}
</Machine>
```

#### state: xstate [state](https://xstate.js.org/api/classes/state.html).
```jsx
<Machine {...} >
  {({ state }) => (
    ...
  )}
</Machine>
```

---
_Source: https://npm.io/package/react-xstate-js · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
