import { useActor } from '@xstate/react';
import { createMachine, fromPromise } from 'xstate';
const fetchUser = fromPromise(async ({ input }: { input: { id: string } }) => {
const response = await fetch(`/api/users/${input.id}`);
return response.json();
});
const userMachine = createMachine({
types: {} as {
input: { userId: string };
context: { user: any; error: any };
},
context: { user: null, error: null },
initial: 'loading',
states: {
loading: {
invoke: {
src: fetchUser,
input: ({ context }) => ({ id: context.userId }),
onDone: {
target: 'success',
actions: assign({
user: ({ event }) => event.output
})
},
onError: {
target: 'failure',
actions: assign({
error: ({ event }) => event.error
})
}
}
},
success: {
on: {
RELOAD: 'loading'
}
},
failure: {
on: {
RETRY: 'loading'
}
}
}
});
function UserProfile({ userId }: { userId: string }) {
const [state, send] = useActor(userMachine, {
input: { userId }
});
if (state.matches('loading')) {
return <div>Loading user...</div>;
}
if (state.matches('failure')) {
return (
<div>
<p>Error: {state.context.error.message}</p>
<button onClick={() => send({ type: 'RETRY' })}>Retry</button>
</div>
);
}
return (
<div>
<h1>{state.context.user.name}</h1>
<p>{state.context.user.email}</p>
<button onClick={() => send({ type: 'RELOAD' })}>Reload</button>
</div>
);
}