Created
November 24, 2019 22:18
-
-
Save RafalFilipek/1d9b38b350abe6db5f23433a1f5b9204 to your computer and use it in GitHub Desktop.
1 hour with xstate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* xstate - 4.7.0-rc.6 | |
* typescript - 3.7.2 | |
*/ | |
import React from "react"; | |
import { createMachine, assign } from "xstate"; | |
import { useMachine } from "@xstate/react"; | |
interface Context { | |
name?: string; | |
} | |
type Event = { type: "SET_NAME"; name: string } | { type: "RESET" }; | |
type State = | |
| { value: "unknown"; context: Context } | |
| { value: "named"; context: Context & { name: string } }; | |
const m = createMachine<Context, Event, State>( | |
{ | |
initial: "named", | |
states: { | |
unknown: { | |
on: { SET_NAME: { target: "named", actions: ["cacheName"] } } | |
}, | |
named: { | |
on: { | |
RESET: { target: "unknown", actions: ["resetName"] } | |
} | |
} | |
} | |
}, | |
{ | |
actions: { | |
// No easy way to make types correct (`event` should be `SET_NAME`) | |
cacheName: assign({ name: (_ctx, event) => event.name }) | |
// can't omit arguments like | |
resetName: assign({ name: () => undefined }) | |
} | |
} | |
); | |
const App = () => { | |
const [current, send] = useMachine(m); | |
if (current.matches("named")) { | |
{ | |
/* `context.name` should be `string` instead of `string | undefined` */ | |
} | |
return <span>{current.context.name.toUpperCase()}</span>; | |
} | |
return ( | |
<div> | |
<button onClick={() => send({ type: "SET_NAME", name: "Rafał" })}> | |
set | |
</button> | |
</div> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is my simplest / final version. I've tried using
Machine(...)
,useMachine
from@xstate/fsm
and some other combinations. I know I can useas
in some places or simple if and checks in render phrase. Hope there are some less manual solutions :)