Štosdenfer
Štosdenfer2w ago

Validate dynamic route ID

When creating dynamic routes in Nextjs, how do we validate that the slug is a valid ID? This is what I have so far:
import { preloadQuery } from "convex/nextjs";
import { api } from "@/convex/_generated/api";
import OrderDetails from "@/components/order-details";

export default async function OrderPage({
params,
}: {
params: Promise<{ orderId: string }>;
}) {
const orderId = await params;

try {
const preloadedOrder = await preloadQuery(api.orders.getOrder, orderId);
} catch (err) {
console.log("invalid id", err);
return <div>Invalid order id</div>;
}

return (
<div>
<OrderDetails />
</div>
);
}
import { preloadQuery } from "convex/nextjs";
import { api } from "@/convex/_generated/api";
import OrderDetails from "@/components/order-details";

export default async function OrderPage({
params,
}: {
params: Promise<{ orderId: string }>;
}) {
const orderId = await params;

try {
const preloadedOrder = await preloadQuery(api.orders.getOrder, orderId);
} catch (err) {
console.log("invalid id", err);
return <div>Invalid order id</div>;
}

return (
<div>
<OrderDetails />
</div>
);
}
export const getOrder = query({
args: {
orderId: v.id("orders"),
},
handler: async (ctx, args) => {
return await ctx.db.get(args.orderId);
},
});
export const getOrder = query({
args: {
orderId: v.id("orders"),
},
handler: async (ctx, args) => {
return await ctx.db.get(args.orderId);
},
});
3 Replies
Convex Bot
Convex Bot2w ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
deen
deen7d ago
only convex itself can validate an _id. you're doing it correctly in the args validator. an alternative, if you don't want to automatically throw an args validation error, is to accept the id as a string, then validate with ctx.db.normalizeId - then do what you wish with the result.
Štosdenfer
ŠtosdenferOP7d ago
I used normalizeId, thank you! For anyone coming by this in the future, this is how I did it:
export const getOrder = query({
args: {
orderId: v.string(),
},
handler: async (ctx, args) => {
const validId = ctx.db.normalizeId("orders", args.orderId);

if (!validId) {
return null;
}

return await ctx.db.get(validId);
},
});
export const getOrder = query({
args: {
orderId: v.string(),
},
handler: async (ctx, args) => {
const validId = ctx.db.normalizeId("orders", args.orderId);

if (!validId) {
return null;
}

return await ctx.db.get(validId);
},
});
// /orders/[orderId]/page.tsx
import { preloadedQueryResult, preloadQuery } from "convex/nextjs";
import { api } from "@/convex/_generated/api";
import OrderDetails from "@/components/order-details";
import { notFound } from "next/navigation";

export default async function OrderPage({
params,
}: {
params: Promise<{ orderId: string }>;
}) {
const orderId = await params;

const preloadedOrder = await preloadQuery(api.orders.getOrder, orderId);
const queryResult = preloadedQueryResult(preloadedOrder);
if (!queryResult) {
notFound();
}

return (
<>
<OrderDetails preloadedOrder={preloadedOrder} />
</>
);
}
// /orders/[orderId]/page.tsx
import { preloadedQueryResult, preloadQuery } from "convex/nextjs";
import { api } from "@/convex/_generated/api";
import OrderDetails from "@/components/order-details";
import { notFound } from "next/navigation";

export default async function OrderPage({
params,
}: {
params: Promise<{ orderId: string }>;
}) {
const orderId = await params;

const preloadedOrder = await preloadQuery(api.orders.getOrder, orderId);
const queryResult = preloadedQueryResult(preloadedOrder);
if (!queryResult) {
notFound();
}

return (
<>
<OrderDetails preloadedOrder={preloadedOrder} />
</>
);
}

Did you find this page helpful?