Skip to content

Commit

Permalink
xstate snippets
Browse files Browse the repository at this point in the history
  • Loading branch information
SandroMaglione committed Nov 1, 2024
0 parents commit 59c4021
Show file tree
Hide file tree
Showing 15 changed files with 738 additions and 0 deletions.
33 changes: 33 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# Dependencies
node_modules
.pnp
.pnp.js

# Local env files
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
_env.ts

# Testing
coverage

# Build Outputs
.next/
out/
build
dist


# Debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Misc
.DS_Store
*.pem
16 changes: 16 additions & 0 deletions fetch-on-mount-with-xstate/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"author": "Sandro Maglione <[email protected]>",
"license": "MIT",
"devDependencies": {
"@types/node": "^22.8.6",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"typescript": "^5.6.3"
},
"dependencies": {
"@xstate/react": "^4.1.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"xstate": "^5.18.2"
}
}
170 changes: 170 additions & 0 deletions fetch-on-mount-with-xstate/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 88 additions & 0 deletions fetch-on-mount-with-xstate/src/machine.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { useMachine } from "@xstate/react";
import { assign, fromPromise, setup } from "xstate";

type Input = Readonly<{ id: number }>;
type Post = Readonly<{
userId: number;
id: number;
title: string;
body: string;
}>;

const machine = setup({
types: {
// 👇 Context contains possible `error` and `post`
context: {} as { error: unknown | null; post: Post | null },
input: {} as Input,

// 👇 Initial default event (https://stately.ai/docs/input#initial-event-input)
events: {} as Readonly<{ type: "xstate.init"; input: Input }>,
},
actors: {
/// 👇 Fetch request inside an actor
fetch: fromPromise(({ input }: { input: Input }) =>
fetch(`https://jsonplaceholder.typicode.com/posts/${input.id}`).then(
async (response) => (await response.json()) as Post
)
),
},
actions: {
onUpdateError: assign((_, { error }: { error: unknown }) => ({ error })),
onUpdatePost: assign((_, { post }: { post: Post }) => ({ post })),
},
}).createMachine({
context: { error: null, post: null },
initial: "Loading",
// 👇 Execute the actor at the start ("on mount")
invoke: {
src: "fetch",
// 👇 Input from component
input: ({ event }) => {
if (event.type === "xstate.init") {
return event.input;
}

throw new Error("Missing machine input");
},
onError: {
target: ".Error",
actions: {
type: "onUpdateError",
// 👇 When error response set `error` in context
params: ({ event }) => ({ error: event.error }),
},
},
onDone: {
target: ".Success",
actions: {
type: "onUpdatePost",
// 👇 When successful response set `user` in context
params: ({ event }) => ({ post: event.output }),
},
},
},
states: {
Loading: {},
Error: {},
Success: {},
},
});

export default function Page() {
const [snapshot] = useMachine(machine, {
input: { id: 1 },
});

// 👇 Match on states instead of brittle multiple `useState`
return (
<div>
{snapshot.matches("Loading") && <span>Loading...</span>}
{snapshot.matches("Error") && (
<pre>{JSON.stringify(snapshot.context.error, null, 2)}</pre>
)}
{snapshot.matches("Success") && (
<pre>{JSON.stringify(snapshot.context.post, null, 2)}</pre>
)}
</div>
);
}
21 changes: 21 additions & 0 deletions fetch-on-mount-with-xstate/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,
"jsx": "react-jsx",
"verbatimModuleSyntax": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"module": "preserve",
"noEmit": true,
"lib": ["es2022", "DOM"]
},
"include": ["**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
17 changes: 17 additions & 0 deletions upload-file-xstate-machine-with-effect/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"author": "Sandro Maglione <[email protected]>",
"license": "MIT",
"devDependencies": {
"@types/node": "^22.8.6",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"typescript": "^5.6.3"
},
"dependencies": {
"@xstate/react": "^4.1.3",
"effect": "^3.10.8",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"xstate": "^5.18.2"
}
}
Loading

0 comments on commit 59c4021

Please sign in to comment.