4

In my Next.js project, I created an express like route->middleware->endpoint pattern using next-connect package.

I have this route pattern:

/api/tours 

/api/tours/:id

/api/tours/top-5-cheap

/api/tours/stats

/api/tours/monthly-plan
...

In my pages/api/tours/index.js file I added a route to capture api/tours and all other subroutes like api/tours/top-5-cheap. According to the docs this should work. But only api/tours works correctly and any request to api/tours/subroute gives a page not found error.Docs: next-connect

import nc from 'next-connect'
const mainRoute = nc({ attachParams: true })

const subRoute1 = nc().use(mid1).get((req, res) => { res.end("api/tours/top-5-cheap") });
const subRoute2 = nc().use(mid2).use(mid3).post(endpoint2);
const subRoute3 = nc().use(mid4).use(mid5).use(mid6).get((req, res) => { res.end("api/tours/monthly-plan") })
    
mainRoute
    .use("/top-5-cheap", subRoute1)
    .use("/stats", subRoute2)
    .use("/monthly-plan", subRoute3)
    .get((req, res) => { res.end("api/tours") })

export default mainRoute

I want to be able to capture all requests to api/tours and api/tours/subroute from pages/api/index.js file rather than creating a file for each subroute Any suggestions or helps are welcome

ABDULLOKH MUKHAMMADJONOV
  • 4,249
  • 3
  • 22
  • 40

1 Answers1

3

You're getting a 404: Page not found error, because the page doesn't exist. Next.JS routing methods, means that api/tours/top-5-cheap will go to /pages/api/top-5-cheap.js. And if it doesn't exist, it returns an error.

NOTE: You can do this without the next-connect package with Next.JS file-based routing system.

Without next-connect

Here are two of my possible solutions

  • Create a new file and enclose the name in brackets ([]) to make it a dynamic route.
└── pages
    └── api
        └── tours
            ├── index.js
            └── [id].js

And use the useRouter hook or one of the data-fetching methods, to access the dynamic parameter

// pages/tours/[id].js
import { useRouter } from 'next/router';

const Post = () => {
  const router = useRouter();
  return <p>Post: {router.query.id}</p>
}
  • you can send a request to the base route and pass the sub-route as a query
www.example.com/api/tours?id=top-5-cheap

And

// pages/api/tours/index.js
export default function (req, res) {
  // sub-route id will be passed in params object
  const id = req.params.id // top-5-cheap; ...
  
  res.send(`Requested ${id} api page`)
}

With next-connect

You can’t use Next.JS server with it’s file-based routing and the next-connect package, so you’ll have to use a custom server.

Read the official docs on Using a Custom Server.

Remember you’ll have to disable the file-based routing to work like you want it to.

// next.config.js
module.exports = {
  useFileSystemPublicRoutes: false,
}
a.mola
  • 3,883
  • 7
  • 23
  • You are defining `subRoute` and `mainRoute` in `server.js` file. But I don't have a custom server in my project. I am using Next.js's directory based routing. Can you please provide an example implementation. – ABDULLOKH MUKHAMMADJONOV Oct 02 '21 at 09:26
  • I thought you were a custom server, I didn’t really mean `server.js`, I just copied the snippet you used in your question so I could pass the `top-5-cheat` as an id query @ABDULLOKHMUKHAMMADJONOB – a.mola Oct 02 '21 at 09:34
  • @ABDULLOKHMUKHAMMADJONOB. Did my answer solve the problem? – a.mola Oct 04 '21 at 14:36
  • Here you go https://chat.stackoverflow.com/rooms/237814/next-js-routing-with-next-connect-for-subroutes – a.mola Oct 05 '21 at 08:28