deno.land / x / jotai@v1.8.4 / docs / integrations / xstate.mdx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
---title: XStatedescription: This doc describes `jotai/xstate` bundle.nav: 4.04---
This doc describes `jotai/xstate` bundle.
Jotai's state management is primitive and flexible,but that sometimes means too free.XState is a sophisticated library to providea better and safer abstraction for state management.
## Install
You have to install `xstate` to access this bundle and its functions.
```npm install xstate# oryarn add xstate```
## atomWithMachine
`atomWithMachine` creates a new atom with XState machine.It receives a function `getMachine` to create a new machine.`getMachine` is invoked at the first use with `get` argument,with which you can read other atom values.
```tsximport { useAtom } from 'jotai'import { atomWithMachine } from 'jotai/xstate'import { assign, createMachine } from 'xstate'
const createEditableMachine = (value: string) => createMachine<{ value: string }>({ id: 'editable', initial: 'reading', context: { value, }, states: { reading: { on: { dblclick: 'editing', }, }, editing: { on: { cancel: 'reading', commit: { target: 'reading', actions: assign({ value: (_, { value }) => value, }), }, }, }, }, })const defaultTextAtom = atom('edit me')const editableMachineAtom = atomWithMachine((get) => // `get` is available only for initializing a machine createEditableMachine(get(defaultTextAtom)))
const Toggle = () => { const [state, send] = useAtom(editableMachineAtom) return ( <div> {state.matches('reading') && ( <strong onDoubleClick={send}>{state.context.value}</strong> )} {state.matches('editing') && ( <input autoFocus defaultValue={state.context.value} onBlur={(e) => send({ type: 'commit', value: e.target.value })} onKeyDown={(e) => { if (e.key === 'Enter') { send({ type: 'commit', value: e.target.value }) } if (e.key === 'Escape') { send('cancel') } }} /> )} <br /> <br /> <div> Double-click to edit. Blur the input or press <code>enter</code> to commit. Press <code>esc</code> to cancel. </div> </div> )}```
## Restartable machine stored in a global Provider (provider-less mode)
When your machine reaches its final state it cannot receive any more events.If your atomWithMachine is initialized in global scope (aka provider-less mode),to restart it you need to send a `RESTART` event to your machine like so:
```tsximport { RESTART } from 'jotai/xstate'
const YourComponent = () => { const [current, send] = useAtom(yourMachineAtom) const isFinalState = current.matches('myFinalState') useEffect(() => { // restart globally initialized machine on component unmount return () => { if (isFinalState) send(RESTART) } }, [isFinalState])}```
### Examples
Check examples with atomWithMachine:
<CodeSandbox id="gxwnx" />Restartable machine:
<CodeSandbox id="zur3wg" />
jotai

Version Info

Tagged at
a year ago