Pass fetched data from getStaticPaths to getStaticProps #11272
-
Edit by @leerob: see updated response here. The SSG documentation recommends to fetch the data for the list of path params in getStaticPaths and fetch data for the individual pages in getStaticProps. When using a GraphQL API for fetching data, this results in possibly redundant calls to the API: all the props needed for the individual pages can already be fetched in one single API call in getStaticPaths. But as far as I know, there is no way to pass this extra data along to getStaticProps yet. If I add another key to paths, I get the error: llustrationCurrent way (paraphrased from the docs)export async function getStaticPaths() {
const posts = await query(`
query {
posts {
id
}
}
`)
const paths = posts.map(post => ({
params: { id: post.id },
}))
return { paths, fallback: false }
}
export async function getStaticProps(context) {
const post = await query(
`query {
post(id: $id) {
title
body
}
}`,
{ variables: { id: context.params.id }}
)
return {
props: { post },
}
} Hypothetical way in which all data is fetched at onceexport async function getStaticPaths() {
const posts = await query(`
query {
posts {
id
title
body
}
}
`)
const paths = posts.map(post => ({
params: { id: post.id },
// additional key for passing along data
content: {
...post
}
}))
return { paths, fallback: false }
}
export async function getStaticProps(context) {
return {
props: { context.content },
}
} This would reduce boilerplate code and (potentially significant) numbers of API roundtrips when working with GraphQL, thereby reducing buildtime. Is this already possible and if not, are there any plans of making this possible in the future? Thank you for your time! |
Beta Was this translation helpful? Give feedback.
Replies: 82 comments 58 replies
-
Hi, this sounds related to #10933 and this comment specifically #10933 (comment) can help you achieve caching data needed multiple times in |
Beta Was this translation helpful? Give feedback.
-
I was hoping for the same thing. Seems that the only value I'm able to pass from |
Beta Was this translation helpful? Give feedback.
-
Hello, I am having the same issue/requirement. I want to pass additional data from getStaticPaths to getStaticProps. Nothing major, just an additional ID so that in getStaticProps I would be able fetch all of the data for the page with that ID. This would be the equivalent to Gatsby's 'context' object in their 'createPage' function. |
Beta Was this translation helpful? Give feedback.
-
The usecase @simonzsolt89 mentions is exactly what I am after too. Seems like this would be the ideal way for the dataflow. |
Beta Was this translation helpful? Give feedback.
-
I'm encountering this issue as well. I want to generate static pages with URLs that do not contain an ID. My CMS only has the ability to directly query an item by ID, not by the fields I'd like to slugify and put in the URL. The best solution would be to pass the ID from In this example, the |
Beta Was this translation helpful? Give feedback.
-
Is there a solution for this? |
Beta Was this translation helpful? Give feedback.
-
Is this still active? I am encountering this issue as well. It would be great to be able to pass a little more context to getStaticPaths but it looks like attributes are getting stripped In between |
Beta Was this translation helpful? Give feedback.
-
Would be useful. I want to fetch more data in |
Beta Was this translation helpful? Give feedback.
-
I'd really like to be able to 'overload' the params returned in Edit: After some reconsideration I think not having the id in the url would anyway be a problem when using |
Beta Was this translation helpful? Give feedback.
-
Same problem here... I need my URLs to be in a readable format so I use a slug, but then I don't have access to ID... Anyone could help? |
Beta Was this translation helpful? Give feedback.
-
I am also facing this issue and the idea of storing the mapping on the filesystem doesn't sound very clean. |
Beta Was this translation helpful? Give feedback.
-
Just chiming in to say was also fighting with this exact same issue and also hate the idea of using an fs cache as a work around. Just seems very hacky for such a seemingly simple problem. |
Beta Was this translation helpful? Give feedback.
-
UPDATE: I was maybe getting ahead of myself, and was a bit too optimistic. Although the below project is a good starting point, it will not work. I made some very silly mistakes, to begin with, and I haven't considered some use cases. 🙈 Sorry for teasing anybody. If my free time allows, I may have a further look and actually finish it. Hi folks, just wanted to let you know, I created a package that abstracts away the fs cache 🎉 You use it like this: import getAllStaticData from "get-all-static-data"
const pageData = getAllStaticData({
async getData() {
return [{ slug: "/testing/foo/bar", title: "Foo", updated: "2020-10-11" }]
},
pathMapper: element => element.slug,
})
export const getStaticPaths = pageData.getStaticPaths(require("fs"))
export const getStaticProps = pageData.getStaticProps(require("fs"))
export default function Test({ data }) {
return <pre>{JSON.stringify(data, null, 2)}</pre>
} Please see the repo for docs 📚, and open an issue if you have any questions. Also, if you have any ideas, please let me know! PS: I could not require/import import getAllStaticData from "get-all-static-data"
export const {getStaticPaths, getStaticProps} = getAllStaticData({
async getData() {
return [{ slug: "/testing/foo/bar", title: "Foo", updated: "2020-10-11" }]
},
pathMapper: element => element.slug,
})
export default function Test({ data }) {
return <pre>{JSON.stringify(data, null, 2)}</pre>
} DISCLAIMER: I put this together in an hour, haven't even tested outside of my dev environment, so 🐛 are inevitable. 🤓 |
Beta Was this translation helpful? Give feedback.
-
Same issue, I need to webscrape a page for header footer elements. I want this to be done at build time for pages but would like to avoid having to scrape the same elements 9000 times during build..... Any ideas? |
Beta Was this translation helpful? Give feedback.
-
Tbf since my original comment Ive come around to this pattern. Separating
business logic and path generation feels right - especially when dealing
with huge numbers of pages
…On Sun, 3 Apr 2022, 10:54 Balsee, ***@***.***> wrote:
Yeah, had a really similar problem today. It's crazy that it's still not a
feature...
—
Reply to this email directly, view it on GitHub
<#11272 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ALSIKRDD7OE5WAXBTM3NTC3VDFMEVANCNFSM4LRGVXJA>
.
You are receiving this because you commented.Message ID: <vercel/next.
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
I have a need for this. In our project, all the paths and pages are managed in the CMS. We have a single template on our front end with [[...path]].js in our root. The downside to our CMS is that we cannot easily query content by the path. So we would like to pass a page id along to getStaticProps as a part of the context. Ideally we could just extend the context and add a few additional properties. |
Beta Was this translation helpful? Give feedback.
-
I also would like to see this feature; my use case requires an additional partition key for fetching a single item but I can not currently pass the data. |
Beta Was this translation helpful? Give feedback.
-
I'm having an issue that is a little bit similar to this. I'm trying to fetch data from GraphQL API endpoint with the getStaticProps data-fetching method. Everything works fine in the function, even when I log the result from the API, I can see it in the terminal. But, when I try to render the data on the page through the props, I get a reference error.
export default function BlogPage() {
const result = articles;
console.log(result);
return (
<React.Fragment>
<Head>
<title>Blog</title>
</Head>
<Container>
<h3>Blog</h3>
{articles.map((post) => {
return <p>{post.title}</p>;
})}
</Container>
</React.Fragment>
);
}
export async function getStaticProps() {
let articles = await getArticles();
console.log(articles);
return {
props: {
articles,
},
};
} |
Beta Was this translation helpful? Give feedback.
-
This usecase is so common that it has to be covered. I can't make the same request twice, it is really bad in terms of performance. |
Beta Was this translation helpful? Give feedback.
-
Any updates on this? Or is there any plan to include more context data for static paths? I have an API - a list of countries that will create the static paths - but the API also has information about each country needed for each static page. I have the data when creating the static paths and would be neat to also pass extra context data instead of having to ping the same API in the static props again to fetch the same data. |
Beta Was this translation helpful? Give feedback.
-
I also need this... I have to specify the type of the content: Is it a "post"? Is it a "page"? Is it a "category"? Because all my pages should be accessible under a simple slug without subdirectories. Depending on the content type I want to load a different component. Is there any way to accomplish this? |
Beta Was this translation helpful? Give feedback.
-
Does the new data fetching paradigm in Next13 basically make the need for this obsolete? |
Beta Was this translation helpful? Give feedback.
-
Well, there are. The new fetch paradigms are opt-in beta right now and are
showing a few limitations so I wouldn't write `getStatic...` methods off
just yet.
… Message ID: ***@***.***
.com>
|
Beta Was this translation helpful? Give feedback.
-
Not sure why the fetch above is considered a solution, maybe I've been tracking the wrong issue all along? because my understanding is that |
Beta Was this translation helpful? Give feedback.
-
why below code not work at all ?
// [title].js
export async function getStaticPaths() {
const ids = await getPostsIds();
// ids[0] =
// {
// id: '/Users/xgqfrms-mm/Documents/github/nextjs-ssr/posts/markdown.md',
// year: '2022',
// month: '12',
// day: '31',
// title: 'last'
// }
const paths = ids.map(({id, year, month, day, title}) => ({
params: {
// id can not pass `id` with params ❌
id,
year,
month,
day,
title,
},
// can not pass `id` by using key out of `params` ❌❌
id,
}));
return {
paths,
fallback: false,
};
}
export async function getStaticProps({ params, id }) {
console.log(`params without id =`, params);
// params without id = {
// params: { year: '2022', month: '12', day: '31', title: 'last' },
// locales: undefined,
// locale: undefined,
// defaultLocale: undefined
// }
// both not work ❌
// const data = await getPostsData(params.id);
const data = await getPostsData(id);
return {
props: {
postData: data,
},
};
}
// [title].js
export async function getStaticPaths() {
const ids = await getPostsIds();
const paths = ids.map(({id, year, month, day, title}) => ({
params: {
year,
month,
day,
title,
},
}));
return {
paths,
fallback: false,
};
}
export async function getStaticProps({ params }) {
// hack way find id ✅
const ids = await getPostsIds();
const obj = ids.find(obj => {
if(obj.year === params.year && obj.month === params.month && obj.day === params.day && obj.title === params.title) {
return obj;
}
});
const data = await getPostsData(obj.id);
return {
props: {
postData: data,
},
};
} |
Beta Was this translation helpful? Give feedback.
-
Encountering the same issue here - simply need an extra freeform No idea why there need to be limitations on the kind of data passed between functions? The feeling that I get is that Next.js is treating me a bit like a child and saying "Oh no no, you've built the object wrong, we don't allow you to be creative here. Please walk back into the safe area." |
Beta Was this translation helpful? Give feedback.
-
Hey folks, for those of you exploring the |
Beta Was this translation helpful? Give feedback.
-
We solved this by saving the JSON that we needed from getStaticPaths in an intermediate file in the public directory. In getStaticProps, we just loaded the JSON from the same file. Worked fine when deployed to Vercel. Imported the the node apis
In getStaticPaths, added the following
Here, In getStaticProps, we added the following
|
Beta Was this translation helpful? Give feedback.
-
With the stable App Router in 13.4, data can be fetched, cached, and shared between your component (rendering) and generating static pages ( |
Beta Was this translation helpful? Give feedback.
With the stable App Router in 13.4, data can be fetched, cached, and shared between your component (rendering) and generating static pages (
generateStaticParams
). This works either usingfetch
caching, or usingcache()
.