Esteban89
Esteban89

Reputation: 691

Using router inside getStaticProps

I'm trying to fetch data from an API that varies depending on the URL, trying to do it with withRouter but it seems it won't work inside getStaticProps.

I currently have the following code:

export async function getStaticProps({ router }) {
const pageRequest = `http://localhost:3000/api/posts/${router.query.pid}`
const res = await fetch(pageRequest)
const json = await res.json()
return {
    props: {
        json,
    },
}
}

It's returning:

TypeError: Cannot read property 'query' of undefined

What's the proper way to get the variable in the URL to use inside getStaticProps?

Upvotes: 11

Views: 16222

Answers (3)

Nikolai Kiselev
Nikolai Kiselev

Reputation: 6613

The getStaticProps function primarily runs at build time, so there is no router available.

If the dynamic route looks like /pages/[pid].js you can access pid at context.params.pid as the following:

export async function getStaticProps(context) {
  const pid = context.params.pid
  return {
    props: {}, // will be passed to the page component as props
  }
}

Keep in mind that using static export with dynamic routes requires getStaticPaths. You'd need to specify all possible IDs.

export async function getStaticPaths() {
  return {
    paths: [
      { params: { pid: '1' } },
      { params: { pid: '2' } }
    ],
    fallback: true or false // See the "fallback" section below
  };
}

Also, you can't use Next.js API routes of the same project in getStaticProps as it's executed at build time without a server running. Instead, you can fetch data directly from the database.

Check out getStaticProps docs for more examples and details.

Alternatively, consider fetching data on the client side.

Upvotes: 26

Ayo Adesina
Ayo Adesina

Reputation: 2425

Another way to solve this problem is to change the architecture of your API.

(I know this may not always be possible or practical) but...

If you change the API so that you don't need to pass it an ID, but instead return all the data in one API call. That way you don't need to use router inside getStaticProps.

Then in your nextjs app you can query the response of the API and by using router inside your component.

I know this is going to depend on how large the data coming back from the API would be, and if you own the API end point and can change it.

Just an idea.

Upvotes: 0

DennieCodes
DennieCodes

Reputation: 71

I'm not sure if this will work for your situation but if you use can getServerSideProps instead, you can get the query id with the following:

export async function getServerSideProps({ query }) {
  const pageRequest = `http://localhost:3000/api/posts/${query.pid}`
  const res = await fetch(pageRequest)
  const json = await res.json()

  return {
    props: {
        json,
    },
  }
}

I know that there are different considerations for using either getStaticProps or getServerSideProps but as described by Nikolai in his answer there are many more steps needed to work with getStaticProps in this situation.

Upvotes: 3

Related Questions