Skip to content

Instantly share code, notes, and snippets.

@ganapativs
Last active July 20, 2022 19:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ganapativs/688026d7eb2c8a34f029b91379253251 to your computer and use it in GitHub Desktop.
Save ganapativs/688026d7eb2c8a34f029b91379253251 to your computer and use it in GitHub Desktop.
Signup state machine using xstate
import React, { useState } from "react";
import { Machine, assign } from "xstate";
import { useMachine } from "@xstate/react";
const signupUser = email =>
new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("You are signed up!");
reject("Unable to sign you up :(");
}, 1000);
});
const signUpMachine = Machine({
id: "signup",
initial: "idle",
context: {
message: ""
},
states: {
idle: {
on: {
SUBMIT: [
{
target: "loading",
// TODO - Validate email here
cond: (context, event) => event.data.email !== "",
actions: assign({
message: (context, event) => "Signing you up..."
})
},
{
target: "error",
actions: assign({
message: (context, event) => "Please enter a valid email"
})
}
]
}
},
loading: {
invoke: {
id: "submitSignup",
src: (context, event) => signupUser(event.data.email),
onDone: {
target: "success",
actions: assign({
message: (context, event) => event.data
})
},
onError: {
target: "error",
actions: assign({
message: (context, event) => event.data
})
}
}
},
success: {
type: "final"
},
error: {
on: {
SUBMIT: [
{
target: "loading",
// TODO - Validate email here
cond: (context, event) => event.data.email !== "",
actions: assign({
message: (context, event) => "Signing you up..."
})
},
// Incase user removes email
{
target: "error",
actions: assign({
message: (context, event) => "Please enter a valid email"
})
}
]
}
}
}
});
function App() {
const [machine, send] = useMachine(signUpMachine);
const [form, updateForm] = useState({ email: "" });
return (
<div className="App">
{machine.context.message ? machine.context.message : null}
{!machine.matches("success") ? (
<form
onSubmit={e => {
e.preventDefault();
send({ type: "SUBMIT", data: form });
}}
>
<input
type="email"
name="email"
onChange={e => {
updateForm({ ...form, email: e.target.value });
}}
/>
<button type="submit">Submit</button>
</form>
) : null}
</div>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment