Spoeky
Spoeky
TtRPC
Created by Spoeky on 10/28/2023 in #❓-help
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 as an input the same as omitting an input ╰──── Maybe one of these should be marked as a client entry with "use client": ./src\app_trpc\client.ts ./src\app\page.tsx
2 replies