Skip to content

Instantly share code, notes, and snippets.

@UberMouse
Created October 20, 2022 21:27
Show Gist options
  • Save UberMouse/91c10f0cd6fb245b60e936d87c1e4360 to your computer and use it in GitHub Desktop.
Save UberMouse/91c10f0cd6fb245b60e936d87c1e4360 to your computer and use it in GitHub Desktop.
import { z } from "zod";
import { makeEndpoint, makeApi, Zodios } from "@zodios/core";
import { QueryClient } from "@tanstack/query-core";
const UserSchema = z.object({
name: z.string(),
country: z.string().nullable()
});
const getUser = makeEndpoint({
method: "get",
path: "/api/user/:id",
alias: "getUser",
response: UserSchema,
});
const api = makeApi([getUser]);
const client = new Zodios("baseUrl", api);
const queryClient = new QueryClient();
const apiClient = new ZodiosObservables("api-id", client, queryClient);
// Creates an instance of a query by alias
const getUserQuery = apiClient.createGetUser();
// combine any queries the machine needs into one observable
const queries = combineApiQueries(getUserQuery);
// the event the combined query observable emits whenever a rueqy updates
// {type: "apiClient.sync", queries: {getUser: QueryResultFromQueryClient }}
type Events = ApiClientEvents<typeof queries>
type Context = {user: z.infer<typeof UserSchema> }
const machine = createMachine({
initial: "loading",
invoke: {
// start the queries off with an intial config and subscribe the machine to the observable
src: () => queries.start({ getUser: { request: { params: { id: "123" } } } })
},
on: {
// Handle any updates that aren't handled by a more specific state
// in this example that would be the updated user loaded in the loaded state, or for handling
// the refetched data if the cache was hot in the loading state, since the stale data will transition it to loaded
// and then in loaded the refetch event will be emitted
"apiClient.sync": {actions: "saveUserData" }
},
states: {
loading: {
on: {
// Detect when the query has loaded successfully
"apiClient.sync": {
cond: (_ctx, e) => e.getUser.isFetched && e.getUser.status === "success",
actions: "saveUserData"
target: "loaded"
}
}
},
loaded: {
// Fetch a different user object which will get loaded into the machine by the top level sync handler
entry: () => getUserQuery.updateConfig({request: { params: { id: "12345" } }})
}
}
}, {actions: { saveUserData: assign((ctx, e)) => { e.getUser.data && ctx.user = e.getUser.data }}})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment