Skip to main content
Glama
tanstack-query.md3.81 kB
```typescript import { useQuery, useMutation, useQueryClient, QueryClient, QueryClientProvider, } from '@tanstack/react-query'; import axios from 'axios'; // ============================================ // Setup // ============================================ // Create a client export const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 1000 * 60 * 5, // 5 minutes gcTime: 1000 * 60 * 30, // 30 minutes retry: 1, refetchOnWindowFocus: false, }, }, }); // API Client const api = axios.create({ baseURL: '/api', }); // ============================================ // Types // ============================================ interface Post { id: number; title: string; body: string; } interface CreatePostDto { title: string; body: string; } // ============================================ // Hooks // ============================================ // Fetch posts export const usePosts = (limit = 10) => { return useQuery({ queryKey: ['posts', limit], queryFn: async () => { const { data } = await api.get<Post[]>(`/posts?limit=${limit}`); return data; }, placeholderData: (previousData) => previousData, // Keep previous data while fetching }); }; // Fetch single post export const usePost = (id: number) => { return useQuery({ queryKey: ['post', id], queryFn: async () => { const { data } = await api.get<Post>(`/posts/${id}`); return data; }, enabled: !!id, // Only fetch if id is present }); }; // Create post mutation export const useCreatePost = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (newPost: CreatePostDto) => { const { data } = await api.post<Post>('/posts', newPost); return data; }, onMutate: async (newPost) => { // Optimistic Update await queryClient.cancelQueries({ queryKey: ['posts'] }); const previousPosts = queryClient.getQueryData<Post[]>(['posts']); queryClient.setQueryData<Post[]>(['posts'], (old) => [ { id: Date.now(), ...newPost }, // Temporary optimistic post ...(old || []), ]); return { previousPosts }; }, onError: (err, newPost, context) => { // Rollback on error if (context?.previousPosts) { queryClient.setQueryData(['posts'], context.previousPosts); } }, onSettled: () => { // Refetch to ensure data is correct queryClient.invalidateQueries({ queryKey: ['posts'] }); }, }); }; // ============================================ // React Components // ============================================ export const PostsList = () => { const { data: posts, isLoading, isError } = usePosts(); if (isLoading) return <div>Loading...</div>; if (isError) return <div>Error loading posts </div>; return ( <ul> { posts?.map((post) => ( <li key= { post.id } > { post.title } </li> ))} </ul> ); }; export const CreatePostForm = () => { const mutation = useCreatePost(); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); mutation.mutate({ title: 'New Post', body: 'Content...' }); }; return ( <form onSubmit= { handleSubmit } > <button disabled={ mutation.isPending }> { mutation.isPending ? 'Creating...' : 'Create Post' } </button> { mutation.isError && <div>Error: { mutation.error.message } </div> } </form> ); }; ```

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/millsydotdev/Code-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server