Web tRPC Setup Skill
When to Use
- User needs to add data fetching to a component
- User wants to create a new tRPC query or mutation
- User needs to set up React Query with tRPC
- User asks to add form submission with tRPC
What This Skill Does
- Determines if query or mutation is needed
- Creates proper tRPC procedure calls
- Handles loading, error, and success states
- Sets up proper React Query options
- Adds cache invalidation for mutations
- Implements proper TypeScript typing
Query Pattern
"use client";
import { trpc } from "@/lib/trpc";
export function useActivities() {
const { data, isLoading, error, refetch } = trpc.activities.list.useQuery(
{ limit: 20, offset: 0 },
{
staleTime: 5 * 60 * 1000,
refetchOnWindowFocus: false,
},
);
return { data, isLoading, error, refetch };
}
Mutation Pattern
"use client";
import { trpc } from "@/lib/trpc";
import { toast } from "sonner";
export function useCreateActivity() {
const utils = trpc.useUtils();
const mutation = trpc.activities.create.useMutation({
onSuccess: () => {
utils.activities.list.invalidate();
toast.success("Activity created");
},
onError: (error) => {
toast.error(error.message);
},
});
return mutation;
}
Error Handling
if (isLoading) return <Skeleton />;
if (error) return <ErrorAlert message={error.message} />;
Loading States
import { Skeleton } from '@/components/ui/skeleton';
function ActivityList() {
const { data, isLoading } = trpc.activities.list.useQuery();
if (isLoading) {
return (
<View className="p-4">
{Array.from({ length: 5 }).map((_, i) => (
<Skeleton key={i} className="h-24 mb-4" />
))}
</View>
);
}
return <ActivityListView activities={data} />;
}
Cache Invalidation
// Invalidate after mutation
utils.activities.list.invalidate();
// Invalidate specific item
utils.activities.getById.invalidate({ id });