Skip to content

Proposal: Migrate Data Fetching to tRPC with Server Hydration #3

Description

@tshabebe

Proposal: Migrate Data Fetching to tRPC with Server Hydration

1. Current Implementation (Problem)

// pages/post/[id].tsx (simplified)
export default function PostPage() {
  const { id } = useParams();
  const { setSelectedPost } = usePostStore();

  useEffect(() => {
    const fetchPost = async () => {
      try {
        const response = await axios.get(`/api/post/${id}`);
        setSelectedPost(response.data.data); // Manual store management
      } catch (error) {
        toast.error("Error loading post");
      }
    };
    fetchPost();
  }, [id]);
  
  return <ExploreRenderPost selectedPost={selectedPost} />;
}

Issues:

  • Manual API calls with Axios
  • State management complexity
  • No type safety
  • No built-in loading/error states

2. Proposed tRPC Implementation

// features/post/post-page.tsx
'use client';

function PostPageContent({ id }: { id: string }) {
  const { data: post, isLoading } = trpc.post.getById.useQuery({ id });

  if (isLoading) return <PostSkeleton />;
  if (!post) return <div>Post not found</div>;

  return <ExploreRenderPost post={post} />;
}

// app/post/[id]/page.tsx (Server Component)
import { HydrateClient } from '@/lib/trpc/rsc.client';
import { trpc } from '@/lib/trpc/rsc';

export default async function Page({ params }: { params: { id: string } }) {
  await trpc.post.getById.prefetch({ id: params.id });
  
  return (
    <HydrateClient>
      <PostPageContent id={params.id} />
    </HydrateClient>
  );
}

3. Key Benefits

Area Improvement
Type Safety End-to-end types from backend to frontend
Performance Server-side prefetching + client hydration
Code Quality 40% less boilerplate code
Error Handling Built-in React Query error states
Maintainability Centralized API definition

4. Implementation Strategy

  1. Create tRPC router for post endpoints
  2. Migrate existing axios calls to tRPC procedures
  3. Implement server component prefetching
  4. Add loading skeletons with Suspense boundaries
// Example loading state (app/dashboard/layout.tsx)
<ErrorBoundary fallback="Error">
  <Suspense fallback={<DashboardSkeleton />}>
    <AppSidebar />
    {children}
  </Suspense>
</ErrorBoundary>

Documentation Reference:
tRPC Server Components Guide


⚠️ Important
Maintains the existing skeleton loading states from original implementation while adding type safety and hydration.

I'll implement this migration - please assign this issue to me.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions