I'm trying to statically export a next.js app. The docs says the page object has only 2 values: page and query. 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's query 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 a routeInfo.json which is prefetched for every route. I wonder if there is anything similar to it in next.js.
UPD Apr 4 20
At least in the next.js 9.3 there are getStaticProps and getStaticPaths
(complete example)
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: "/" }
});
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With