Next.js Discord

Discord Forum

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

Unanswered
Miniature Schnauzer posted this in #help-forum
Open in Discord
Avatar
Miniature SchnauzerOP
Hello, 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:

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

    // Render table with ingresos data
}


However, I'm encountering an error when trying to fetch the data from the API route in the server component. The error message is "Failed to parse URL from /api/ingresos".

I understand that server components run on the server and don't have access to the same base URL as client-side code. But I'm not sure how to correctly fetch data from a local API route in a server component.

Moreover, 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!

17 Replies

Avatar
Large garden bumble bee
You shouldn't be fetching data from yourself, instead if it is a server component then put the database query in the server component
it doesnt pose any security risk as the functions nor data wont be transfered to client unless you say so
Avatar
Tramp ant
if you must though, you just need the full url of your server: https://github.com/vercel/next.js/discussions/49740

but this will not work with static route generation
I personally do this when i need to cache db driver calls in a dynamic route, since api routes can be cached
but it does trigger a new request from the server component to your api, nextjs will not bridge this internally
Avatar
Miniature SchnauzerOP
Thank you for your previous response, it was really helpful and cleared up a lot of my confusion. I now understand that server components can directly fetch data, which simplifies the process significantly. However, I'm still curious about the role of API routes in this context. If we can fetch data directly in server components, what specific use cases or scenarios are there where API routes would still be necessary or beneficial? Why do API routes exist if we can handle data fetching directly in server components?
Avatar
Alfonsus Ardani
API routes are used for external API access outside of your Next.js Application.
Or client-side fetching (if you don't want to use Server Actions)
Avatar
Miniature SchnauzerOP
Thanks for the explanation! It's becoming clearer now. I have a follow-up question. I'm planning to use a client component to make a POST request to add data to my database with the click of a button. I'm considering using an API route that has both GET and POST handlers. Would this be a good approach? And if so, how could I integrate the GET functionality with the example I showed earlier? Any guidance would be greatly appreciated. Thank you!
Avatar
Alfonsus Ardani
Its the standard approach so.. i dont see any guidance needed
this is the wrong format to declare the routes
Image
this is the documentation if you are using route.ts in /app dir
Avatar
Miniature SchnauzerOP
My apologies for the confusion earlier. I mistakenly used an older version of the code in my question. I've updated my code to follow the Next.js 13 documentation for route handlers. Here's the correct code for my API route:

// 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 })
  }      
}


With this updated setup, I'm able to get the correct response when I visit the /api/ingresos route in my browser (I'll attach a screenshot to show this). However, I'm still unsure about how to use this API route in my tablaIngresosCliente.tsx page component to fetch the data. If you don't want to provide guidance because it's in the docs, that's totally fine. I appreciate your help so far! Thank you!
Image
Avatar
Miniature SchnauzerOP
export default async function TablaIngresos() {
    const ingresos: Ingreso[] = await fetch('http://localhost:3000/api/ingresos').then(res => 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: Ingreso, 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>
    );
}
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? Thanks for all your help up to this point!