Reputation: 691
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
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
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
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