Next.js Discord

Discord Forum

How to use server component in a client component (in pages /directory)

Answered
Philippine Crocodile posted this in #help-forum
Open in Discord
Philippine CrocodileOP
// @/lib/trpc/server
import 'server-only';

import { cache } from 'react';
import { headers } from 'next/headers';

import { createCaller, createTRPCContext } from '@orbitkit/api';

const createContext = cache(async () => {
  const heads = new Headers(headers());
  heads.set('x-trpc-source', 'rsc');

  return createTRPCContext({
    headers: heads,
  });
});

export const api = createCaller(createContext);


'use client';
import { api } from '@/lib/trpc/server';
import { GenresNav } from '@/components/GenresNav';
import { useState } from 'react';

const Dashboard = async () => {
  const genres = await api.home.allGenres();
  const [selectedLink, setSelectedLink] = useState('All');



I am getting an error
You're importing a component that needs server-only. That only works in a Server Component which is not supported in the pages/ directory.

its not a fetch/ REST API but a TRPC call
how do you properly do the data fetching within the client component? does it need to move to layout.tsx & how?
thanks
Answered by Philippine Crocodile
ok the issue was i imported api from @trpc/server but I needed to use the { api } from @trpc/client for client component ✅

now I am looking into a trpc related bug https://github.com/trpc/trpc/issues/3496#issuecomment-2042379723
View full answer

9 Replies

Philippine CrocodileOP
Netherland Dwarf
Server components cant be imported in client
@Philippine Crocodile
Philippine CrocodileOP
thanks @Netherland Dwarf
actually i have a client within pages
import { type NextRequest } from 'next/server';

import { fetchRequestHandler } from '@trpc/server/adapters/fetch';

import { appRouter, createTRPCContext } from '@orbitkit/api';
import { env } from '@orbitkit/env/web';

const createContext = async (req: NextRequest) => {
  return createTRPCContext({
    headers: req.headers,
  });
};

const handler = (req: NextRequest) =>
  fetchRequestHandler({
    endpoint: '/api/trpc',
    req,
    router: appRouter,
    createContext: () => createContext(req),
    onError: ({ path, error }) => {
      if (env.NODE_ENV === 'development') {
        console.error(
          `❌ tRPC failed on ${path ?? '<no-path>'}: ${error.message}`,
        );
      }
    },
  });

export { handler as GET, handler as POST };


however I did not import it and was using the server api directly.
how do i import it and call the api.home.allGenres endpoint?
sorry, i think that is still the server-side handler. how do i send the data it fetched to the client component?
Netherland Dwarf
You pass the data down as props to the client comp
Philippine CrocodileOP
i have useState, setState, and an onChange function in the parent
they dont work because useState requires "use client" in the parent
import 'server-only';

import { cache } from 'react';
import { headers } from 'next/headers';

import { createCaller, createTRPCContext } from '@orbitkit/api';

const createContext = cache(async () => {
  const heads = new Headers(headers());
  heads.set('x-trpc-source', 'rsc');

  return createTRPCContext({
    headers: heads,
  });
});

export const api = createCaller(createContext);

this code is the server side component for trpc
if I remove import 'server-only'; to use the Caller in client comp, it complains that import { headers } from 'next/headers'; doesnt work in client components

any advice? thanks
Philippine CrocodileOP
if the client component makes a selection it needs to call a parent handler or pass it backwards to the parent to re-render something
Philippine CrocodileOP
ok the issue was i imported api from @trpc/server but I needed to use the { api } from @trpc/client for client component ✅

now I am looking into a trpc related bug https://github.com/trpc/trpc/issues/3496#issuecomment-2042379723
Answer