4
votes

When fetching data using getServerSideProps() in Next.js, they recommend directly importing the API endpoint instead of using fetch() and running another HTTP request. This makes sense, and I was able to get it working until implemented middleware for my API (note, I'm using the API feature built into Next.js). Now with middleware implemented, I can't export functions that use the middleware, I have to export the handler. See below:

const handler = nextConnect();
handler.use(middleware);

handler.get(async (req, res) => {
    const post = await req.db.collection("posts").findOne();
    res.send({
        post: post,
    });
});

export default handler;

What would be the recommend way to import my API endpoint into getServerSideProps? I would like to do something as follows, but the getPost() function no longer has access to the database middleware:

export const getPost = async () => {
    const post = await req.db.collection("posts").findOne();
    return post;
}

handler.get(async (req, res) => {
    res.send({
        post: getPost(),
    });
});

and then in my next.js page:

import { getPost } from './api/post';
...
export async function getServerSideProps(context) {
    return {
        props: {
            post: getPost(),
        }
    }
}
1
If you give me more info on the setup of your project, in particular your database, I can totally solve the problem for you and earn that bounty ;) - demux

1 Answers

0
votes

In any case, you'll have to pass the req and res objects to the function. But if you do the following, the post prop should be populated with a NextApiResponse instance, which at it's base is a stream.Writable object, which is probably not what you want...

import { getPost } from './api/post';
...
export async function getServerSideProps({req, res}) {
  return {
    props: {
      post: await getPost(req, res),
    }
  }
}

You could try to read the stream, but that seems like more trouble than refactoring your code, but if you call getPost(req, res).end(), I think you should get the streamed data, but I'm not sure how it will be formatted. You'd have to check.

You could split your functions up a little more..

// In your api endpoint:
const handler = nextConnect();
handler.use(middleware);

export async function getPostMethod(db) {
  return await db.collection("posts").findOne();
}

handler.get(async (req, res) => {
  res.send({
    post: await getPostMethod(req, res, req.db)
  })
});

export default handler;

// In your page component:

export async function getServerSideProps({req, res}) {
  // Do what ever you have to do here to get your database connection
  const db = await whereIsMyDb()
  return {
    props: {
      post: await getPostMethod(db),
    }
  }
}