#Dynamic routes in App router
1 messages · Page 1 of 1 (latest)
Yes, it is possible to have dynamic routes in Next.js like the structure you provided. In Next.js, dynamic routes can be created by wrapping a folder's name in square brackets, such as [category] or [region]. These dynamic segments are filled in at request time or prerendered at build time.
Here's how your structure would work:
category/[category]/[region]/EventCategoryRegion.tsxandcategory/[category]/[region]/page.tsxwould correspond to URLs like/category/books/asia/EventCategoryRegionand/category/books/asia, withbooksandasiabeing the dynamic[category]and[region]respectively.category/[category]/EventCategoryClient.tsxandcategory/[category]/page.tsxwould correspond to URLs like/category/books/EventCategoryClientand/category/books, withbooksbeing the dynamic[category].
Remember, the dynamic segments ([category] and [region]) are passed as the params prop to layout, page, route, and generateMetadata functions.
For more information, you can refer to the Next.js documentation on Dynamic Routes (https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) and generateStaticParams (https://nextjs.org/docs/app/api-reference/functions/generate-static-params).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@mild rose kapa.ai is still learning and improving, please let us know how it did by reacting below
@daring wharf this is our server function in events/category/[category]/page.tsx file. Is this correct way of using params? If not, whats the better alternative?: import getCurrentUser from '@/app/actions/getCurrentUser';
import ClientOnly from '@/app/components/ClientOnly';
import EmptyState from '@/app/components/EmptyState';
import EventCategoryClient from './EventCategoryClient';
interface IParams {
category?: string;
}
const EventCategoryPage = async ({ params }: { params: IParams }) => {
const currentUser = await getCurrentUser();
const { category } = params;
const url = new URL(${process.env.NEXT_PUBLIC_API_URL}/api/events/category);
if (category) {
url.searchParams.append('category', category);
}
const response = await fetch(url.toString(), { cache: 'force-cache' });
const events = await response.json();
if (!events) {
return <EmptyState />;
}
return (
<ClientOnly>
<EventCategoryClient events={events} currentUser={currentUser} />
</ClientOnly>
);
};
export default EventCategoryPage;
Let me check the knowledge base for you. One moment! :books:
The code you provided seems to be a mix of server-side and client-side logic. In Next.js, you typically separate these concerns.
For server-side data fetching, you would use getServerSideProps or getStaticProps. These functions run on the server-side and can be used to fetch data and pass it as props to your page.
However, in your case, you're using an async function directly in your component. This isn't the typical way to handle server-side data fetching in Next.js.
Here's an example of how you might refactor your code to use getServerSideProps:
import { GetServerSideProps } from 'next';
import getCurrentUser from '@/app/actions/getCurrentUser';
import ClientOnly from '@/app/components/ClientOnly';
import EmptyState from '@/app/components/EmptyState';
import EventCategoryClient from './EventCategoryClient';
interface IParams {
category?: string;
}
interface IProps {
events: any; // replace with your actual type
currentUser: any; // replace with your actual type
}
export const getServerSideProps: GetServerSideProps<IProps, IParams> = async ({ params }) => {
const currentUser = await getCurrentUser();
const { category } = params;
const url = new URL(`${process.env.NEXT_PUBLIC_API_URL}/api/events/category`);
if (category) {
url.searchParams.append('category', category);
}
const response = await fetch(url.toString(), { cache: 'force-cache' });
const events = await response.json();
return {
props: {
events,
currentUser,
},
};
};
const EventCategoryPage = ({ events, currentUser }: IProps) => {
if (!events) {
return <EmptyState />;
}
return (
<ClientOnly>
<EventCategoryClient events={events} currentUser={currentUser} />
</ClientOnly>
);
};
export default EventCategoryPage;
In this refactored code, getServerSideProps is used to fetch the data on the server-side. The fetched data is then passed as props to the EventCategoryPage component.
Please note that this is just a suggestion and might need adjustments based on your actual use case and data types.
For more information, you can refer to the Next.js documentation on Data Fetching (https://nextjs.org/docs/basic-features/data-fetching).
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@mild rose kapa.ai is still learning and improving, please let us know how it did by reacting below
@daring wharf But as I told you, we are using App router.
Let me check the knowledge base for you. One moment! :books:
I apologize for the confusion. In the context of the App Router, you would use a route.tsx file to handle server-side data fetching. The route.tsx file exports a handle function that can be used to fetch data and return a response.
Here's an example of how you might refactor your code to use a route.tsx file:
// events/category/[category]/route.tsx
import { handle } from 'next/app';
import getCurrentUser from '@/app/actions/getCurrentUser';
export default handle({
async request(request) {
const currentUser = await getCurrentUser();
const { category } = request.params;
const url = new URL(`${process.env.NEXT_PUBLIC_API_URL}/api/events/category`);
if (category) {
url.searchParams.append('category', category);
}
const response = await fetch(url.toString(), { cache: 'force-cache' });
const events = await response.json();
return {
props: {
events,
currentUser,
},
};
},
});
Then, in your page.tsx file, you would receive the events and currentUser as props:
// events/category/[category]/page.tsx
import ClientOnly from '@/app/components/ClientOnly';
import EmptyState from '@/app/components/EmptyState';
import EventCategoryClient from './EventCategoryClient';
interface IProps {
events: any; // replace with your actual type
currentUser: any; // replace with your actual type
}
const EventCategoryPage = ({ events, currentUser }: IProps) => {
if (!events) {
return <EmptyState />;
}
return (
<ClientOnly>
<EventCategoryClient events={events} currentUser={currentUser} />
</ClientOnly>
);
};
export default EventCategoryPage;
Please note that this is just a suggestion and might need adjustments based on your actual use case and data types.