You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将_app的getServerSideProps数据传递给页面的getServerSideProps?

能否将_app的getServerSideProps数据传递给页面的getServerSideProps?

场景描述

我有一个自定义的_app组件,其中包含getServerSideProps方法,在此处验证用户是否已认证,若已认证则从数据库加载用户数据,随后将isAuthenticated和user这两个值传递给_app的props。

同时我还有多个实际页面,部分公开、部分需要权限校验,这些页面也有自己的getServerSideProps方法。我希望在页面的getServerSideProps中直接复用_app里已加载的用户数据,避免两次加载用户信息——一次在_app层面,一次在页面层面。

现有代码示例

// pages/_app.jsx

const App = ...

App.getServerSideProps = async(context) => {
    let isAuthenticated = false;
    let user = {};

    if (context?.req) {
        // get token from Cookies, validate token & load user
    }

    return {
        props: { isAuthenticated, user },
    }
}
// pages/profile.jsx

const ProfilePage = ...

ProfilePage.getServerSideProps = async(context) => {
    // get token, load user - in this step, I'd like to reuse the previously loaded data

    if (!isAuthenticated || !user.HAS_SOME_SPECIFIC_PERMISSION) {
        return {
            redirect: {
                destination: '/login',
            },
        }
    }

    return { props: {} }
}

解决方案

Next.js中,_app的getServerSideProps和页面的getServerSideProps是独立执行的,但两者共享同一次请求的req对象。我们可以利用这一点,通过提取公共认证逻辑+请求级缓存的方式实现数据复用:

1. 提取公共认证函数

创建一个独立的工具函数,封装用户认证、数据加载逻辑,并将结果缓存到req对象上:

// utils/auth.js
export async function getUserFromRequest(req) {
    // 优先读取请求缓存的用户数据
    if (req.userData) {
        return req.userData;
    }

    let isAuthenticated = false;
    let user = {};

    if (req) {
        // 从Cookie获取token、验证并加载用户数据的逻辑
        // 示例:
        // const token = req.cookies.token;
        // if (token) {
        //   user = await db.user.findUnique({ where: { token } });
        //   isAuthenticated = !!user;
        // }
    }

    // 将数据缓存到req对象,供同一次请求的后续调用复用
    req.userData = { isAuthenticated, user };
    return req.userData;
}

2. 在_app中使用公共函数

修改_app的getServerSideProps,调用公共函数获取用户数据:

// pages/_app.jsx
import { getUserFromRequest } from '../utils/auth';

const App = ({ Component, pageProps, isAuthenticated, user }) => {
    return <Component {...pageProps} isAuthenticated={isAuthenticated} user={user} />;
};

App.getServerSideProps = async (context) => {
    const userData = await getUserFromRequest(context.req);
    return {
        props: { ...userData },
    };
};

export default App;

3. 在页面中复用数据

页面的getServerSideProps同样调用公共函数,此时会直接读取req上缓存的数据,无需重复查询数据库:

// pages/profile.jsx
import { getUserFromRequest } from '../utils/auth';

const ProfilePage = () => {
    return <div>Profile Page</div>;
};

ProfilePage.getServerSideProps = async (context) => {
    const { isAuthenticated, user } = await getUserFromRequest(context.req);

    if (!isAuthenticated || !user.HAS_SOME_SPECIFIC_PERMISSION) {
        return {
            redirect: {
                destination: '/login',
            },
        };
    }

    return { props: {} };
};

export default ProfilePage;

补充说明

  • 该方案仅适用于Next.js Pages Router,App Router的逻辑会有差异。
  • 因为是基于请求级缓存,每次请求都会重新加载用户数据,不会出现跨请求的脏数据问题。

内容的提问来源于stack exchange,提问作者Patrik Šimunič

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 08:54:24