Fetching Data from API Route in Next.js 13 Server Component
Asked Answered
F

3

7

I'm currently learning Next.js 13 and I'm trying to fetch data from a PocketBase database to display in a table. I've created an API route that connects to the database and retrieves the data. However, I'm having trouble fetching this data in a server component.

Here's the structure of my project:

app/
  api/
    ingresos/
      route.ts
  components/
    tablaIngresosCliente.tsx
  ingresos/
    page.tsx
  ...

In route.ts, I connect to the PocketBase database and fetch the data:

// app/api/ingresos/route.ts
import { NextResponse } from 'next/server';
import PocketBase from 'pocketbase';

export async function GET(request: Request) {
  const pb = new PocketBase('http://127.0.0.1:8090');
  try {
    const records = await pb.collection('ingresos').getFullList({
      sort: '-created',
    });
    return NextResponse.json(records);
    
  } catch (error) {
    console.error(error)
    return new Response('Could not fetch', { status: 500 })
  }      
}

In tablaIngresosCliente.tsx, I'm trying to fetch the data from the API route:

// app/components/tablaIngresosCliente.tsx
export default async function TablaIngresos() {
    const res = await fetch('/api/ingresos');
    const ingresos = await res.json();

    return (
        <div className="flex flex-col">
            <div className="overflow-x-auto sm:-mx-6 lg:-mx-8">
                <div className="inline-block min-w-full py-2 sm:px-6 lg:px-8">
                    <div className="overflow-hidden">
                        <table className="min-w-full text-center text-sm font-light">
                            <thead className="border-b bg-neutral-800 font-medium text-white dark:border-neutral-500 dark:bg-neutral-900">
                                <tr>
                                    <th scope="col" className=" px-6 py-4">#</th>
                                    <th scope="col" className=" px-6 py-4">Fuente</th>
                                    <th scope="col" className=" px-6 py-4">Cantidad</th>
                                    <th scope="col" className=" px-6 py-4">Fecha</th>
                                </tr>
                            </thead>
                            <tbody>
                                {ingresos.map((item, index) => (
                                    <tr key={index} className="border-b dark:border-neutral-500">
                                        <td className="whitespace-nowrap  px-6 py-4 font-medium">{index + 1}</td>
                                        <td className="whitespace-nowrap  px-6 py-4">{item.fuente}</td>
                                        <td className="whitespace-nowrap  px-6 py-4">{item.cantidad}</td>
                                        <td className="whitespace-nowrap  px-6 py-4">{item.fecha}</td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    );
}

With this setup, I'm able to get the correct response when I visit the /api/ingresos route in my browser. However, I'm still unsure about how to use this API route in my tablaIngresosCliente.tsx page component to fetch the data.

I'm aware that I could potentially use server component actions, but I chose this approach because I plan to use a client component to make a POST request to add new data to the database. I thought that using the API route would be a good way to handle both GET and POST requests.

I'm wondering if this is the correct approach for fetching data in Next.js 13. Is it recommended to fetch data from an API route in a server component, or is there a better way to fetch and display data in Next.js 13?

Any guidance would be greatly appreciated. Thank you!

Fulgurating answered 1/8, 2023 at 4:51 Comment(1)
"export default async function TablaIngresos() { const ingresos: Ingreso[] = await fetch('localhost:3000/api/ingresos').then(res => res.json()); return (" This seems to work well for fetching data from my API route in a server component. However, I'm still curious about whether this is considered good practice in Next.js 13. Is it recommended to fetch data from an API route in a server component like this, or is there a better way to do it?Fulgurating
J
2

You can not fetch from API routes (rather handler - GET, POST etc. that you export from route.ts) in server components. You should extract the fetching logic to util function and use that instead to fetch data in server component.

API routes can be called only from client components.

Jun answered 1/8, 2023 at 9:51 Comment(5)
Are you sure? I can fetch data from /app/api/test/route.js inside /app/test/page.jsx simply: export default async function SqlPage() { const data = await fetch('http://localhost:3001/api/test').then((res) => res.json() ); console.log('data is', data); return <div>yes</div>; } Glendoraglendower
Are you able to build and run successfully or it is just working in dev mode?Jun
Earlier this was not possible as api routes were not guaranteed to work while generating the components server side.Jun
Yes; it's not just for dev mode.Glendoraglendower
This isn't correct. You can fetch data from API endpoint from a server component in NextJS 13.4.+Tractate
C
0

I agree, using fetch in api route is a pain, the api returns {Digest: DYNAMIC_SERVER_USAGE} instead of the server response in PROD mode, otherwise i can get data correctly in DEV mode (nextjs 13.5.6)

Charie answered 27/10, 2023 at 9:52 Comment(0)
L
-1

Try simply delete your .next folder, works for me.

Lofty answered 24/12, 2023 at 7:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.