{"id":13727329,"url":"https://github.com/carloslfu/use-machine","last_synced_at":"2025-04-05T22:08:24.696Z","repository":{"id":33281061,"uuid":"156098877","full_name":"carloslfu/use-machine","owner":"carloslfu","description":"React Hook for using Statecharts powered by XState. use-machine.","archived":false,"fork":false,"pushed_at":"2023-01-03T16:36:12.000Z","size":797,"stargazers_count":226,"open_issues_count":15,"forks_count":12,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-29T21:05:43.359Z","etag":null,"topics":["react","react-hook","state-machine","state-management","statecharts","use-machine","xstate"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/carloslfu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-04T15:56:24.000Z","updated_at":"2024-04-15T21:12:57.000Z","dependencies_parsed_at":"2023-01-15T00:21:27.381Z","dependency_job_id":null,"html_url":"https://github.com/carloslfu/use-machine","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carloslfu%2Fuse-machine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carloslfu%2Fuse-machine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carloslfu%2Fuse-machine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carloslfu%2Fuse-machine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/carloslfu","download_url":"https://codeload.github.com/carloslfu/use-machine/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247406091,"owners_count":20933803,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["react","react-hook","state-machine","state-management","statecharts","use-machine","xstate"],"created_at":"2024-08-03T01:03:50.015Z","updated_at":"2025-04-05T22:08:24.583Z","avatar_url":"https://github.com/carloslfu.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.com/carloslfu/use-machine.svg?branch=master)](https://travis-ci.com/carloslfu/use-machine)\n# use-machine\n\nUse Statecharts in React powered by XState, using the `useMachine` hook. This is a minimalistic implementation (just 30 lines) that integrates React and XState.\n\nInstall it  with: `npm i use-machine`\n\nSee --\u003e [the live example here!](https://codesandbox.io/s/5z0820jlyk).\n\nLet's build something with it:\n\n```javascript\nimport React, { useContext } from 'react'\nimport ReactDOM from 'react-dom'\nimport { assign } from 'xstate/lib/actions'\nimport { useMachine } from 'use-machine'\n\nconst incAction = assign(context =\u003e ({ counter: context.counter + 1 }))\n\nconst machineConfig = {\n  initial: 'Off',\n  context: {\n    counter: 0\n  },\n  states: {\n    Off: { on: { Tick: { target: 'On', actions: [incAction, 'sideEffect'] } } },\n    On: { on: { Tick: { target: 'Off', actions: incAction } } }\n  }\n}\n\nconst MachineContext = React.createContext()\n\nfunction App() {\n  const machine = useMachine(machineConfig, {\n    actions: {\n      sideEffect: () =\u003e console.log('sideEffect')\n    }\n  })\n\n  function sendTick() {\n    machine.send('Tick')\n  }\n\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cspan\n        style={{\n          backgroundColor: machine.state.matches('Off') ? 'red' : 'yellow'\n        }}\n      \u003e\n        {machine.state.matches('Off') ? 'Off' : 'On'}\n      \u003c/span\u003e\n      \u003cbutton onClick={sendTick}\u003eTick\u003c/button\u003e\n      Pressed: {machine.context.counter} times\n      \u003cMachineContext.Provider value={machine}\u003e\n        \u003cdiv className=\"childs\"\u003e\n          \u003cChild /\u003e\n        \u003c/div\u003e\n      \u003c/MachineContext.Provider\u003e\n    \u003c/div\u003e\n  )\n}\n\nfunction Child() {\n  const machine = useContext(MachineContext)\n  return (\n    \u003cdiv\u003e\n      \u003cdiv\u003e\n        Child state: {machine.state.matches('Off') ? 'Off' : 'On'}\n      \u003c/div\u003e\n      \u003cdiv\u003eChild count: {machine.context.counter}\u003c/div\u003e\n      \u003cOtherChild /\u003e\n    \u003c/div\u003e\n  )\n}\n\nfunction OtherChild() {\n  const machine = useContext(MachineContext)\n\n  function sendTick() {\n    machine.send('Tick')\n  }\n  return (\n    \u003cdiv\u003e\n      \u003cdiv\u003e\n        OtherChild state: {machine.state.matches('Off') ? 'Off' : 'On'}\n      \u003c/div\u003e\n      \u003cdiv\u003eOtherChild count: {machine.context.counter}\u003c/div\u003e\n      \u003cbutton onClick={sendTick}\u003eTick 2\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n\nconst rootElement = document.getElementById('root')\nReactDOM.render(\u003cApp /\u003e, rootElement)\n```\n\n## TypeScript\n\nThis library is written in TypeScript, and XState too, so we have excellent support for types.\n\nExample:\n\n```typescript\nimport React, { useContext } from 'react'\nimport ReactDOM from 'react-dom'\nimport { MachineConfig } from 'xstate'\nimport { assign } from 'xstate/lib/actions'\nimport { useMachine, TCreateContext } from './use-machine'\n\ntype TContext = {\n  counter: number\n}\n\ntype TSchema = {\n  states: {\n    Off: {},\n    On: {}\n  }\n}\n\ntype TEvent = {\n  type: 'Tick'\n}\n\nconst incAction = assign\u003cTContext\u003e(context =\u003e ({ counter: context.counter + 1 }))\n\nconst machineConfig: MachineConfig\u003cTContext, TSchema, TEvent\u003e = {\n  initial: 'Off',\n  context: {\n    counter: 0\n  },\n  states: {\n    Off: { on: { Tick: { target: 'On', actions: [incAction, 'sideEffect'] } } },\n    On: { on: { Tick: { target: 'Off', actions: incAction } } }\n  }\n}\n\ntype TMachine = TCreateContext\u003cTContext, TSchema, TEvent\u003e\n\nconst MachineContext = React.createContext\u003cTMachine\u003e({} as TMachine)\n\nfunction App() {\n  const machine = useMachine\u003cTContext, TSchema, TEvent\u003e(machineConfig, {\n    actions: {\n      sideEffect: () =\u003e console.log('sideEffect')\n    }\n  })\n\n  function sendTick() {\n    machine.send('Tick')\n  }\n\n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003cspan\n        style={{\n          backgroundColor: machine.state.matches('Off') ? 'red' : 'yellow'\n        }}\n      \u003e\n        {machine.state.matches('Off') ? 'Off' : 'On'}\n      \u003c/span\u003e\n      \u003cbutton onClick={sendTick}\u003eTick\u003c/button\u003e\n      Pressed: {machine.context.counter} times\n      \u003cMachineContext.Provider value={machine}\u003e\n        \u003cdiv className=\"childs\"\u003e\n          \u003cChild /\u003e\n        \u003c/div\u003e\n      \u003c/MachineContext.Provider\u003e\n    \u003c/div\u003e\n  )\n}\n\nfunction Child() {\n  const machine = useContext(MachineContext)\n  return (\n    \u003cdiv\u003e\n      \u003cdiv\u003e\n        Child state: {machine.state.matches('Off') ? 'Off' : 'On'}\n      \u003c/div\u003e\n      \u003cdiv\u003eChild count: {machine.context.counter}\u003c/div\u003e\n      \u003cOtherChild /\u003e\n    \u003c/div\u003e\n  )\n}\n\nfunction OtherChild() {\n  const machine = useContext(MachineContext)\n\n  function sendTick() {\n    machine.send('Tick')\n  }\n  return (\n    \u003cdiv\u003e\n      \u003cdiv\u003e\n        OtherChild state: {machine.state.matches('Off') ? 'Off' : 'On'}\n      \u003c/div\u003e\n      \u003cdiv\u003eOtherChild count: {machine.context.counter}\u003c/div\u003e\n      \u003cbutton onClick={sendTick}\u003eTick 2\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n\nconst rootElement = document.getElementById('root')\nReactDOM.render(\u003cApp /\u003e, rootElement)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarloslfu%2Fuse-machine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarloslfu%2Fuse-machine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarloslfu%2Fuse-machine/lists"}