简体   繁体   中英

Next.js: pass additional props to the page during static export?

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: "/" }
    });
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM