在 NextJS 中如何将数据从 server.js 传递到 _app.js?

avo*_*ado 5 javascript node.js reactjs next.js

在我的 NextJS 项目中,我使用文件koa中的 Web 框架server.js,我想做的如下,

  1. server.js执行一些外部 api 调用以在每个请求中生成一些自定义数据,
  2. 然后将生成的数据传递给_app.js,以便所有页面可以通过 props 或 context 共享数据。

我的问题是我们如何将生成的数据传递到server.js_app.js页面?

这是一些代码示例,

//////////////////////////////////////////////////
// server.js
import Koa from "koa";
import Router from "koa-router";

const verified_names = {};
const handle = app.getRequestHandler();  // NextJS use this to handle each request

app.prepare().then(async () => {
  const server = new Koa();
  const router = new Router();
  ...

  // in verifyNameFunc, if name is verified, will set verified_names[name] = some_data
  router.get("/verify_name", verifyNameFunc);

  router.get("(.*)", async (ctx) => {
    // custom logic starts here: if name is not verified, redirect to /verify_name
    const name = ctx.query.name;
    if (verified_names[name] === undefined) {
        ctx.redirect(`/verify_name?name=${name}`);
    }
    // HERE: do some external api calls and generate some data
    var custom_data = custom_logic(verified_names[name]);

    // I think here starts rendering the pages (i.e. enters the execution of `_app.js` and pages)
    // QUESTION: how to pass the above `custom_data` to _app.js or pages?
    await handle(ctx.req, ctx.res);  
    }
  });

  server.use(router.routes());
  server.listen(...);
  
});

//////////////////////////////////////////////////
// _app.js

class MyApp extends App {
  ...
}

MyApp.getInitialProps = async ({ ctx }) => {
  // Can we get the `custom_data` from server.js here?
  ...
};
Run Code Online (Sandbox Code Playgroud)

custom_logic我想保留里面的原因server.js是,

  • 如果name未验证,则会发生重定向并将verifyNameFunc一些数据设置到verified_names.

我不确定这个重定向是否_app.js也可以移入?

Rus*_*mir 1

这只是解决方案之一:创建一个单独的 js 文件(模块),您将在其中导出两个函数setData()getData()如下所示:

//////////////////////////////////////////////////
// ./lib/data-manager.js

let promiseResolver = undefined;
const promise = new Promise((resolve) => {
  promiseResolver = resolve;
})

export function setData(data) { promiseResolver(data); }
export function async getData() { return promise; }

//////////////////////////////////////////////////
// server.js
import { setData } from "../lib/data-manager"
import Koa from "koa";
import Router from "koa-router";

const verified_names = {};
const handle = app.getRequestHandler();  // NextJS use this to handle each request

app.prepare().then(async () => {
  const server = new Koa();
  const router = new Router();
  ...

  // in verifyNameFunc, if name is verified, will set verified_names[name] = some_data
  router.get("/verify_name", verifyNameFunc);

  router.get("(.*)", async (ctx) => {
    // custom logic starts here: if name is not verified, redirect to /verify_name
    const name = ctx.query.name;
    if (verified_names[name] === undefined) {
        ctx.redirect(`/verify_name?name=${name}`);
    }
    // HERE: do some external api calls and generate some data
    var custom_data = custom_logic(verified_names[name]);

    setData(custom_data); // <-- saving data

    // I think here starts rendering the pages (i.e. enters the execution of `_app.js` and pages)
    // QUESTION: how to pass the above `custom_data` to _app.js or pages?
    await handle(ctx.req, ctx.res);  
    }
  });

  server.use(router.routes());
  server.listen(...);
  
});

//////////////////////////////////////////////////
// _app.js
import { getData } from "../lib/data-manager"

class MyApp extends App {
  ...
}

MyApp.getInitialProps = async ({ ctx }) => {
  const custom_data = await getData();  // <-- getting data
};


Run Code Online (Sandbox Code Playgroud)

请记住,getInitialProps在页面中启用服务器端渲染并允许您进行初始数据填充,这意味着使用已从服务器填充的数据发送页面(请参阅https://nextjs.org/docs/api-reference/数据获取/getInitialProps)。但是,正如向您推荐的那样,也许您根本不需要自定义服务器