Next.js: pass additional props to the page during static export?
UPD Apr 4 20
At least in the next.js 9.3 there are getStaticProps
and getStaticPaths
const IndexPage: NextPage<{ names: string[] }> = (props) => {
return (
<main>
<section>
{props.names.map((name) => (
<div key={name}>
<Link href={`/users/${name}`}>
<a>{name}</a>
</Link>
</div>
))}
</section>
</main>
);
};
export const getStaticProps: GetStaticProps = async () => {
const data: User[] = readJsonSync("./data.json");
return {
props: {
names: data.map((user) => user.name),
},
};
};
export default IndexPage;
UPD Dec 4 19
There is an RFC for getStaticProps
which solves this: https://github.com/zeit/next.js/issues/9524
Here is what I ended up with.
_app.js:
import React from "react";
import App, { Container } from "next/app";
import fs from "fs";
import { resolve, join } from "path";
export default class extends App {
static async getInitialProps({ Component, ctx }) {
const { req, asPath } = ctx;
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
let p;
if (req) {
p = JSON.parse(
fs.readFileSync(resolve(join("data", asPath, "route.json"))).toString()
);
} else {
p = await (await fetch(`/data${asPath}/route.json`)).json();
}
return { pageProps: { ...pageProps, ...p } };
}
render() {
const { Component, pageProps } = this.props;
return (
<Container>
<Component {...pageProps} />
</Container>
);
}
}
in next.config.js:
const fetch = require("isomorphic-unfetch");
const fs = require("fs");
const path = require("path");
const fse = require("fs-extra");
const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: false
});
module.exports = withBundleAnalyzer({
webpack(config) {
config.node = { fs: "empty", path: "empty" };
return config;
},
async exportPathMap() {
const response = await fetch(
"https://jsonplaceholder.typicode.com/posts?_page=1"
);
const postList = await response.json();
fs.writeFileSync(
path.resolve(`data/route.json`),
JSON.stringify({ postList }, null, 2)
);
for (let i = 0; i < postList.length; ++i) {
const id = postList[i].id;
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts/${id}`
);
const post = await response.json();
const fn = path.resolve(`data/post/${id}/route.json`);
await fse.outputFile(fn, JSON.stringify(post, null, 2));
}
const pages = postList.reduce(
(pages, post) =>
Object.assign({}, pages, {
[`/post/${post.id}`]: {
page: "/post"
}
}),
{}
);
return Object.assign({}, pages, {
"/": { page: "/" }
});
}
});
Evgeny Timoshenko
JavaScript | Node.js Печатные материалы и игры для детей
Updated on June 27, 2022Comments
-
Evgeny Timoshenko almost 2 years
I'm trying to statically export a next.js app. The docs says the page object has only 2 values:
page
andquery
. Is there a way to pass additional props to the page?I've tried to use
query
for this, but it seems that next's router is not aware of the route'squery
object. Hence it didn't work.In other words, I have a list of blog posts at build time, how could I inline them to the page (page component)?
I guess
react-static
has arouteInfo.json
which is prefetched for every route. I wonder if there is anything similar to it in next.js. -
theLucre over 4 yearsThis is awesome, thank you for sharing. I wanted a solution that only requested global data once during compile and never during client side routes. I used your file write from the
exportPathMap
callback to cache a request once during export and accessed the data client side using the__NEXT_DATA__
window global. See conversation here: spectrum.chat/next-js/general/…