#Dynamic Route with @ prepend

1 messages · Page 1 of 1 (latest)

glossy sentinel
#

I have the following requirement:

I have list of usernames without "@" and would to create a dynamic route page for each using generateStaticParams. I am using App router and on v14.2.7

boreal breachBOT
#

Hi @glossy sentinel. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

You can create dynamic routes in Next.js using the generateStaticParams function. This function is used in combination with dynamic route segments to statically generate routes at build time instead of on-demand at request time.

Here's an example of how you can use generateStaticParams to create a dynamic route for each username:

// Return a list of `params` to populate the [username] dynamic segment
export async function generateStaticParams() {
  const users = await fetch('<https://.../users'>).then((res) => res.json())
 
  return users.map((user) => ({
    username: '@' + user.username,
  }))
}
 
// Multiple versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
export default function Page({ params }) {
  const { username } = params
  // ...
}

In this example, generateStaticParams fetches a list of users and returns an array of objects, each containing a username property prefixed with '@'. These username values are used to populate the [username] dynamic segment in your route.

Please note that you must always return an array from generateStaticParams, even if it's empty. Otherwise, the route will be dynamically rendered.

For more information, you can refer to the Next.js documentation on generateStaticParams (https://nextjs.org/docs/app/api-reference/functions/generateStaticParams).

#

However, there's a known issue with Next.js where any page with a dynamic route parameter with a prefix will accept requests to that page even without the prefix. It will also accept any other special character as a prefix. So /_johndoe, /@johndoe and /johndoe will all render the same page. If the parameter were to be something like @not-found the entire app will now accept any string and it will consider it a valid page essentially rendering /_not-found useless. This issue was reported in a Github issue (https://github.com/vercel/next.js/issues/52938).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

To ensure that only the route with '@' prefix (e.g., www.vercel.com/@username) is accepted and not the one without it (e.g., www.vercel.com/username), you can use custom server-side logic to handle the routing.

However, it's important to note that Next.js routing system doesn't distinguish special characters in dynamic routes. As mentioned in the Github issue (https://github.com/vercel/next.js/issues/52938), any page with a dynamic route parameter with a prefix will accept requests to that page even without the prefix.

As a workaround, you can use Serverless Functions (https://vercel.com/docs/functions) to handle the routing based on your requirements. Serverless Functions allow you to write server-side code to handle incoming requests, which means you can write custom logic to handle the routing based on the URL parameters.

Unfortunately, the provided knowledge sources do not include a specific example of how to implement this in Next.js. For more detailed guidance, you may want to refer to the Next.js documentation on API Routes (https://nextjs.org/docs/api-routes/introduction) and Vercel documentation on Serverless Functions (https://vercel.com/docs/serverless-functions/introduction).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
#

@boreal breach How would I use custom server-side logic to handle the routing for the above case? Write the code for the same

boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

To handle custom routing with a server-side logic, you can use a custom server like Express.js or Koa.js. However, please note that using a custom server will remove some of the benefits of Next.js like automatic static optimization and serverless deployment.

Here's an example of how you can use a custom server with Koa.js to handle the routing:

import Koa from 'koa';
import Router from 'koa-router';
import nextApp from 'next';
import { parse } from 'url';

const port = 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = nextApp({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = new Koa();
  const router = new Router();

  router.get('/@:username', async (ctx) => {
    const parsedUrl = parse(ctx.url, true);
    const { query, pathname } = parsedUrl;
    ctx.respond = false; // Bypass Koa's built-in response handling
    ctx.res.statusCode = 200; // Set status code to 200
    await app.render(ctx.req, ctx.res, pathname, { ...query, username: ctx.params.username });
  });

  server.use(router.routes());
  server.use(router.allowedMethods());

  server.use(async (ctx) => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });

  server.listen(port, () => {
    console.log(`> Ready on <http://localhost:${port}`>);
  });
});

In this example, we're using Koa.js and koa-router to create a custom server. We define a route '/@:username' that matches the URLs with '@' prefix and passes the username as a parameter to the Next.js page renderer.

Please note that this is just an example and might need adjustments based on your project setup and requirements.

For more information, you can refer to the Next.js documentation on Custom Server (https://nextjs.org/docs/advanced-features/custom-server) and Koa.js documentation (https://koajs.com/).

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
#

@boreal breach How would I redirect to error page?

boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

In Next.js, you can redirect to an error page by throwing an error in your page's data fetching methods (getServerSideProps, getStaticProps, or getInitialProps). If an error is thrown, Next.js will display the built-in error page or your custom error page if you have one.

Here's an example of how you can redirect to an error page:

import Error from 'next/error'

export async function getServerSideProps() {
  const res = await fetch('<https://api.github.com/repos/vercel/next.js'>)
  const errorCode = res.ok ? false : res.status
  const json = await res.json()

  return {
    props: { errorCode, stars: json.stargazers_count },
  }
}

export default function Page({ errorCode, stars }) {
  if (errorCode) {
    return <Error statusCode={errorCode} />
  }

  return <div>Next stars: {stars}</div>
}

In this example, if the fetch request fails (i.e., res.ok is false), we pass the status code of the response to the Error component, which will display the corresponding error page.

You can also create a custom error page by creating a _error.js (or _error.tsx for TypeScript) file inside the pages directory. This file should export a React component that will be used as the error page.

For more information, you can refer to the Next.js documentation on Error Handling (https://nextjs.org/docs/app/building-your-application/routing/error-handling) and Custom Errors (https://nextjs.org/docs/pages/building-your-application/routing/custom-error#500-page).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
#

@boreal breach For the above dynamic route case, I am adding a condition, if params.username doesn't start with "a", I want to direct to the error page.

if (!username.startsWith('@') || username.length < 5) {
// logic to re-direct here
}

boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

In your case, you can throw an error in your getServerSideProps or getStaticProps function if the username doesn't start with '@' or its length is less than 5. This will cause Next.js to display the error page.

Here's an example of how you can do this:

import Error from 'next/error'

export async function getServerSideProps(context) {
  const { username } = context.params;

  if (!username.startsWith('@') || username.length < 5) {
    // This will display the custom error page with status code 400
    return { props: { errorCode: 400 }};
  }

  // Fetch data and pass it as props
  // ...

  return { props: { /* your props here */ }};
}

export default function Page({ errorCode, /* your props here */ }) {
  if (errorCode) {
    return <Error statusCode={errorCode} />
  }

  // Render your page component
  // ...

  return <div>{/* your page content here */}</div>
}

In this example, if the username doesn't start with '@' or its length is less than 5, we return an errorCode prop with a value of 400. In the page component, we check if errorCode is truthy, and if it is, we render the Error component with the status code passed as a prop.

For more information, you can refer to the Next.js documentation on Error Handling (https://nextjs.org/docs/app/building-your-application/routing/error-handling) and Custom Errors (https://nextjs.org/docs/pages/building-your-application/routing/custom-error#500-page).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
#

@boreal breach But I am using generateStaticParams. Would it still work then?

boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

If you're using generateStaticParams to generate static pages, you can't directly use server-side data fetching methods like getServerSideProps. However, you can still validate the username parameter and handle errors in your page component.

Here's an example of how you can do this:

import Error from 'next/error'

// This function is called at build time and should return a list of params
export async function generateStaticParams() {
  // Fetch your list of usernames and return them as params
  // ...

  return usernames.map((username) => ({
    params: { username: '@' + username },
  }))
}

export default function Page({ params }) {
  const { username } = params

  if (!username.startsWith('@') || username.length < 5) {
    // If the username doesn't start with '@' or its length is less than 5,
    // render the Error component with status code 400
    return <Error statusCode={400} />
  }

  // Render your page component
  // ...

  return <div>{/* your page content here */}</div>
}

In this example, if the username doesn't start with '@' or its length is less than 5, we render the Error component with a status code of 400.

Please note that this is just an example and might need adjustments based on your project setup and requirements.

For more information, you can refer to the Next.js documentation on generateStaticParams (https://nextjs.org/docs/app/api-reference/functions/generateStaticParams) and Error Handling (https://nextjs.org/docs/app/building-your-application/routing/error-handling).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The error message you're seeing is indicating that you're trying to render a React Class Component inside a Server Component. This is not supported in Next.js.

Server Components in Next.js are designed to be used with React function components. If you're using class components, you'll need to convert them to function components or use them inside Client Components.

Here's an example of how you can convert a class component to a function component:

// Class Component
class ExampleClassComponent extends React.Component {
  render() {
    return <div>Hello, {this.props.name}</div>;
  }
}

// Converted to Function Component
function ExampleFunctionComponent(props) {
  return <div>Hello, {props.name}</div>;
}

If you can't convert the class component to a function component, you can use it inside a Client Component. You can create a Client Component by adding 'use client' at the top of your component file:

'use client'

import ExampleClassComponent from './ExampleClassComponent'

export default function ExampleClientComponent(props) {
  return <ExampleClassComponent {...props} />;
}

In this example, ExampleClientComponent is a Client Component that renders ExampleClassComponent, which is a class component.

For more information, you can refer to the Next.js documentation on Server Components (https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#using-third-party-packages-and-providers) and the error message documentation (https://nextjs.org/docs/messages/class-component-in-server-component).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
#

@boreal breach What's wrong with the below GET handler?

export function GET(request: Request) {
const response = NextResponse.next();
return response.cookies.delete("userId");
}

boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The issue with the GET handler you provided is that you're trying to return the result of response.cookies.delete("userId"). The delete method of Cookies doesn't return a response that can be sent back to the client. It just deletes the specified cookie.

Instead, you should delete the cookie and then return the response. Here's how you can do it:

export function GET(request: Request) {
  const response = NextResponse.next();
  response.cookies.delete("userId");
  return response;
}

In this corrected version, we're deleting the "userId" cookie and then returning the response. This will send a response back to the client without the "userId" cookie.

For more information, you can refer to the Next.js documentation on Cookies (https://nextjs.org/docs/app/building-your-application/routing/cookies).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

The error message you're seeing is indicating that you're trying to use NextResponse.next() in an app route handler, which is not supported in Next.js.

The NextResponse.next() method is specifically designed for use in middleware, not in route handlers. It allows you to return early and continue routing in the middleware.

In a route handler, you should return a NextResponse object directly, or use one of its methods like json(), html(), redirect(), etc., to generate a response.

Here's an example of how you can return a JSON response in a route handler:

import { NextResponse } from 'next/server'

export function GET(request) {
  return NextResponse.json({ message: 'Hello, Next.js!' })
}

In this example, we're using the NextResponse.json() method to return a JSON response.

For more information, you can refer to the Next.js documentation on NextResponse (https://nextjs.org/docs/app/api-reference/functions/next-response) and the error message documentation (https://nextjs.org/docs/messages/next-response-next-in-app-route-handler).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
#

@boreal breach Can the above be used to clear the cookie?

boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Yes, you can clear a cookie in a route handler by using the cookies API on the NextResponse object. Here's how you can do it:

import { NextResponse } from 'next/server'

export function GET(request) {
  const response = new NextResponse();
  response.cookies.delete('userId');
  return response;
}

In this example, we're creating a new NextResponse object, deleting the 'userId' cookie, and then returning the response. This will send a response back to the client without the 'userId' cookie.

For more information, you can refer to the Next.js documentation on Cookies (https://nextjs.org/docs/app/api-reference/functions/cookies#deleting-cookies) and NextResponse (https://nextjs.org/docs/app/api-reference/functions/next-response).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@glossy sentinel kapa.ai is still learning and improving, please let us know how it did by reacting below

glossy sentinel
#

@boreal breach I am using App router and would like to clear the cookie when a GET request is send to the route /logout. Write the code

boreal breachBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Sure, you can clear a cookie in an App Route Handler by using the cookies API on the NextResponse object. Here's how you can do it:

import { NextResponse } from 'next/server'

export async function GET(request) {
  const response = new NextResponse();
  response.cookies.delete('userId');
  return response;
}

In this example, we're creating a new NextResponse object, deleting the 'userId' cookie, and then returning the response. This will send a response back to the client without the 'userId' cookie.

You would place this code in a file at pages/app/logout.ts (or logout.js if you're using JavaScript instead of TypeScript). This will create an App Route Handler that responds to GET requests at the /logout route.

For more information, you can refer to the Next.js documentation on Cookies (https://nextjs.org/docs/app/api-reference/functions/cookies#deleting-cookies) and NextResponse (https://nextjs.org/docs/app/api-reference/functions/next-response).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: