Next.js Discord

Discord Forum

Where does the id format get configured in "/invoice/[id]" in the tutorial?

Answered
Gharial posted this in #help-forum
Open in Discord
Avatar
GharialOP
I'm going through the dashboard project tutorial for NextJS and am on Chapter 13: Handling Errors. I was working on implementing the notFound function and noticed something interesting

When I use this link
http://localhost:3000/dashboard/invoices/12/edit
/dashboard/invoices/error.tsx would trigger

When I use this link
http://localhost:3000/dashboard/invoices/2e94d1ed-d220-449f-9f11-f0bbceed9645/edit
/dashboard/invoices/[id]/edit/not-found.tsx would trigger

Where is the id format defined?
Is this a uuid thing or a nextjs thing?
Image
Image
Answered by Ray
export async function fetchInvoiceById(id: string) {
  try {
    const data = await sql<InvoiceForm>`
      SELECT
        invoices.id,
        invoices.customer_id,
        invoices.amount,
        invoices.status
      FROM invoices
      WHERE invoices.id = ${id};
    `;

    const invoice = data.rows.map((invoice) => ({
      ...invoice,
      // Convert amount from cents to dollars
      amount: invoice.amount / 100,
    }));

    return invoice[0];
  } catch (error) {
    console.error("Database Error:", error);
  }
}

this is what i have, yes because you throw it
View full answer

21 Replies

Avatar
GharialOP
here's a link to the tutorial
https://nextjs.org/learn/dashboard-app
Avatar
Ray
I get 404 when visiting to http://localhost:3000/dashboard/invoices/12/edit
but when you get to the error page, it should be something wrong with the fetchInvoiceById function
Avatar
GharialOP
huh interesting. I'll check that out. Weird bug

did you by chance edit the fetchInvoiceById function?

by default they have

export async function fetchInvoiceById(id: string) {
  noStore();

  try {
    const data = await sql<InvoiceForm>`
      SELECT
        invoices.id,
        invoices.customer_id,
        invoices.amount,
        invoices.status
      FROM invoices
      WHERE invoices.id = ${id};
    `;

    const invoice = data.rows.map((invoice) => ({
      ...invoice,
      // Convert amount from cents to dollars
      amount: invoice.amount / 100,
    }));

    return invoice[0];
  } catch (error) {
    console.error('Database Error:', error);
    throw new Error('Failed to fetch invoice.');
  }
}


while in the actions we define the errors like

} catch (error) {
  return { message: 'Database Error: Faied to create invoice.' };
}
maybe because I'm throwing?
I doubt it though
Avatar
Ray
export async function fetchInvoiceById(id: string) {
  try {
    const data = await sql<InvoiceForm>`
      SELECT
        invoices.id,
        invoices.customer_id,
        invoices.amount,
        invoices.status
      FROM invoices
      WHERE invoices.id = ${id};
    `;

    const invoice = data.rows.map((invoice) => ({
      ...invoice,
      // Convert amount from cents to dollars
      amount: invoice.amount / 100,
    }));

    return invoice[0];
  } catch (error) {
    console.error("Database Error:", error);
  }
}

this is what i have, yes because you throw it
Answer
Avatar
Ray
it should return null, if not found instead of throwing
Avatar
GharialOP
Oh got it

i tried to return { message: ... }
and that rendered out the error.tsx

plainly console logging the error though allowed not-found.tsx to load

i'm guessing because of what you're saying about needing to return null
Avatar
Ray
yep then handle it with notFound
Avatar
GharialOP
is that a quirk of a ... - i forget how we classify these here

they're services
but they're not actions

how do we call this kind of function?
thanks for the help btw
Avatar
Ray
query? I don't get it 😆
Avatar
GharialOP
like

/lib/actions.tsx are server actions for Create Update Delete
while /lib/data.tsx are (you're right they totally are just get requests so queries make sense)

trying to understand the distinction associated with the separation because they all fall under (C)reate,(R)ead,(U)pdate,(D)estroy
both working against the same db

just trying to understand their reasoning for separating the GET reqs vs everything else
makes sense

just never seen that distinction before
Avatar
Ray
data layer? data access?
Avatar
GharialOP
im more accustomed to resource1/crud , resource2/crud

vs this being more

cud/all-resources
r/all-resources
Avatar
Ray
page = r
server action = cud
:noice:
Avatar
GharialOP
ill take it lol
appreciate the help 🙏
Avatar
Ray
np please mark solution