tRPCttRPC
Powered by
SpoekyS
tRPC•3y ago•
1 reply
Spoeky

TRPC with Nextjs 13 App Router

Im trying to implement TRPC with my already existing Nextjs 13 App to get typesafe API's. I've managed to get it to work in Client Components, meaning i can make the API Calls from them but whenever I try to use them on a server rendered Page, I keep getting an error. In the tutorials I followed, it worked perfectly fine in the Server Rendered Page so I'm wondering how to fix this.

Related Files:

layout.tsx:

import "./globals.css";
import { Inter } from "next/font/google";
import { ThemeProvider } from "@/src/app/components/providers/ThemeProvider";
import Providers from "./_trpc/Providers";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
    title: "",
    description: "",
};

function RootLayout({ children }: { children: React.ReactNode }) {
    return (
        <html lang="en">
            <Providers>
                <body className={inter.className}>
                    <ThemeProvider attribute="class" defaultTheme="light">
                        {children}
                    </ThemeProvider>
                </body>
            </Providers>
        </html>
    );
}

export default RootLayout;

-------
client.ts

import { AppRouter } from "@/src/server";
import { createTRPCReact } from "@trpc/react-query";

export const trpc = createTRPCReact<AppRouter>({});

--------
Providers.tsx

"use client";

import { trpc } from "@/src/app/_trpc/client";
import { absoluteUrl } from "@/lib/utils";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { httpBatchLink } from "@trpc/client";
import { PropsWithChildren, useState } from "react";

const Providers = ({ children }: PropsWithChildren) => {
    const [queryClient] = useState(() => new QueryClient());
    const [trpcClient] = useState(() =>
        trpc.createClient({
            links: [
                httpBatchLink({
                    url: absoluteUrl("/api/trpc"),
                }),
            ],
        })
    );

    return (
        <trpc.Provider client={trpcClient} queryClient={queryClient}>
            <QueryClientProvider client={queryClient}>
                {children}
            </QueryClientProvider>
        </trpc.Provider>
    );
};

export default Providers;


-----
page.tsx


import PostList from "./components/ui/PostList";
import { getCurrentUser } from "@/lib/session";
import Navbar from "./components/sections/Navbar";
import { fetchPosts } from "@/lib/actions/post.actions";
import BottomNavbar from "./components/sections/BottomNavbar";
import Temp from "./components/Temp";
import { trpc } from "./_trpc/client";

const Home = async () => {
    const user = await getCurrentUser();

    const posts = await fetchPosts();

    const { data } = trpc.posts.getMany.useQuery();

    return (
        <div>
            <Navbar user={user} />
            <Temp />
            <div className="px-4 pt-2 mx-auto max-w-[1245px]">
                <PostList posts={posts} userId={user?.id} />
            </div>
            <BottomNavbar user={user} />
        </div>
    );
};

export default Home;
layout.tsx:

import "./globals.css";
import { Inter } from "next/font/google";
import { ThemeProvider } from "@/src/app/components/providers/ThemeProvider";
import Providers from "./_trpc/Providers";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
    title: "",
    description: "",
};

function RootLayout({ children }: { children: React.ReactNode }) {
    return (
        <html lang="en">
            <Providers>
                <body className={inter.className}>
                    <ThemeProvider attribute="class" defaultTheme="light">
                        {children}
                    </ThemeProvider>
                </body>
            </Providers>
        </html>
    );
}

export default RootLayout;

-------
client.ts

import { AppRouter } from "@/src/server";
import { createTRPCReact } from "@trpc/react-query";

export const trpc = createTRPCReact<AppRouter>({});

--------
Providers.tsx

"use client";

import { trpc } from "@/src/app/_trpc/client";
import { absoluteUrl } from "@/lib/utils";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { httpBatchLink } from "@trpc/client";
import { PropsWithChildren, useState } from "react";

const Providers = ({ children }: PropsWithChildren) => {
    const [queryClient] = useState(() => new QueryClient());
    const [trpcClient] = useState(() =>
        trpc.createClient({
            links: [
                httpBatchLink({
                    url: absoluteUrl("/api/trpc"),
                }),
            ],
        })
    );

    return (
        <trpc.Provider client={trpcClient} queryClient={queryClient}>
            <QueryClientProvider client={queryClient}>
                {children}
            </QueryClientProvider>
        </trpc.Provider>
    );
};

export default Providers;


-----
page.tsx


import PostList from "./components/ui/PostList";
import { getCurrentUser } from "@/lib/session";
import Navbar from "./components/sections/Navbar";
import { fetchPosts } from "@/lib/actions/post.actions";
import BottomNavbar from "./components/sections/BottomNavbar";
import Temp from "./components/Temp";
import { trpc } from "./_trpc/client";

const Home = async () => {
    const user = await getCurrentUser();

    const posts = await fetchPosts();

    const { data } = trpc.posts.getMany.useQuery();

    return (
        <div>
            <Navbar user={user} />
            <Temp />
            <div className="px-4 pt-2 mx-auto max-w-[1245px]">
                <PostList posts={posts} userId={user?.id} />
            </div>
            <BottomNavbar user={user} />
        </div>
    );
};

export default Home;


Here is the Error i get:

You're importing a component that needs useEffect. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.

╭─[@trpc+react-query@10.43.0@tanstack+react-query@4.36.1@trpc+client@10.43.0_@trpc+server@10.4_7lsmxlrq3xi3juoktsh4534bt4\node_modules@trpc\react-query\dist\createHooksInternal-bdff7171.mjs:2:1]
4 │ import { useQuery, useQueryClient, useMutation, hashQueryKey, useInfiniteQuery, useQueries } from '@tanstack/react-query';
5 │ import React, { createContext, useRef, useState, useEffect, useCallback, useMemo } from 'react';
· ─────────
6 │
7 │ /**
8 │ * We treat
undefined
undefined
as an input the same as omitting an
input
input

╰────

Maybe one of these should be marked as a client entry with "use client":
./src\app_trpc\client.ts
./src\app\page.tsx
tRPCJoin
Move Fast & Break Nothing. End-to-end typesafe APIs made easy.
5,015Members
Resources
Was this page helpful?

Similar Threads

Recent Announcements

Similar Threads

tRPC with app router
SzymonSSzymon / ❓-help
3y ago
PersistQueryClientProvider in tRPC NextJS pages router app
Answer OverflowAAnswer Overflow / ❓-help
3y ago
TRPC Nextjs App Router API Base URL
MikeyMMikey / ❓-help
3y ago
trpc with app dir nextjs
MajMMaj / ❓-help
3y ago