Skip to content

Instantly share code, notes, and snippets.

@barrybtw
Created July 10, 2023 14:26
Show Gist options
  • Save barrybtw/e27c8e55ca03040284d68b0e39e076b3 to your computer and use it in GitHub Desktop.
Save barrybtw/e27c8e55ca03040284d68b0e39e076b3 to your computer and use it in GitHub Desktop.
import { useQuery } from '@tanstack/react-query';
import { useQueryClient } from '@tanstack/react-query';
import { z } from 'zod';
import { createZodFetcher } from 'zod-fetch';
const fetchWithZod = createZodFetcher();
const characterSchema = z.object({
info: z.object({
count: z.number(),
pages: z.number(),
next: z.string().nullable(),
prev: z.string().nullable(),
}),
results: z.array(
z.object({
id: z.number(),
name: z.string(),
status: z.string(),
species: z.string(),
type: z.string().nullable(),
gender: z.string().nullable(),
origin: z.object({
name: z.string(),
url: z.string(),
}),
location: z.object({
name: z.string(),
url: z.string(),
}),
image: z.string(),
episode: z.array(z.string()),
}),
),
});
type Characters = z.infer<typeof characterSchema>;
type Character = Characters['results'][number];
const query = async (id: number | undefined) =>
fetchWithZod(
characterSchema,
'https://rickandmortyapi.com/api/character' + (id ? `/${id}` : ''),
);
export const useCharacters = () => {
return useQuery({
queryKey: ['characters'],
queryFn: () => query(undefined),
select: (data) => data.results,
staleTime: 60 * 1000 * 60,
});
};
export const useCharacter = (id: number) => {
const queryClient = useQueryClient();
return useQuery({
queryKey: ['character', id] as const,
queryFn: ({ queryKey }) => {
return query(queryKey[1]);
},
initialData: () => {
return queryClient
.getQueryData<Characters>(['characters'])
?.results.find((character) => character.id === id);
},
initialDataUpdatedAt: () => {
return queryClient.getQueryState(['characters'])?.dataUpdatedAt;
},
staleTime: 60 * 1000 * 60,
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment