动态服务器使用:页面无法静态呈现,因为它使用了“headers”

问题描述 投票:0回答:1

代码

页面组件:

import React from 'react';
import PricingPlansMain from '@/components/pages/PricingPlansPage';
import { getMeAction } from '@/server/auth-actions';
import { getAgentPricingPlansAction } from '@/server/payment-actions';
import PageLayout from '@/components/ui/PageLayout';
import UserCtxLayoutProvider from '@/components/ui/UserCtxLayoutProvider';
import styles from '@/components/pages/PricingPlansPage/styles.module.css';

export default async function PricingPlansPage() {
  const userData = (await getMeAction())?.success;
  const plans = await getAgentPricingPlansAction();

  return (
    <UserCtxLayoutProvider userData={userData}>
      <PageLayout
        headerClass={styles.header}
        headerTheme='light'
        logoConfig={{ theme: 'black', variant: 'full' }}
        headerVersion='full'
        footerTheme='default'
      >
        <PricingPlansMain plans={plans} />
      </PageLayout>
    </UserCtxLayoutProvider>
  );
}

行动:

export const getMeAction = async () => {
  try {
    const res = await fetch(`${process.env.BACKEND_BASE}/users/me`, {
      cache: 'no-store',
      headers: { ...getAuthorizationHeader() },
      next: { tags: [getCacheKey('userData')] },
    });
    if (!res.ok) {
      throw new Error('server_error');
    }
    const { data } = await res.json();
    return { success: data as UserType };
  } catch (err) {
    return { error: 'server_error' };
  }
};
export async function getAgentPricingPlansAction() {
  try {
    const res: Response = await fetch(
      `${process.env.BACKEND_BASE}/payments/plans/prices`,
      {
        method: REQUEST_METHODS.GET,
        headers: {
          ...getNodeRequiredRequestHeaders(),
          ...getAuthorizationHeader(),
        },
      }
    );
    if (!res.ok) {
      throw new Error('unexpected error');
    }
    const data: PricingPlansActionResponseType = await res.json();
    return data;
  } catch (err: any) {
    throw new Error(err.message as string);
  }
}

我在 Next.js 项目中使用 App Router,并在尝试预渲染页面时遇到以下错误:

Error: Dynamic server usage: Page couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error
    at o (D:\upwork\movein\new frontend\muuve-frontend\.next\server\app\(website)\pricing-plans\page.js:1:13234)
    at o (D:\upwork\movein\new frontend\muuve-frontend\.next\server\app\(website)\pricing-plans\page.js:1:12434)
Error occurred prerendering page "/pricing-plans". Read more: https://nextjs.org/docs/messages/prerender-error

当我调用函数从服务器获取定价计划时,会发生错误。但是,如果我注释掉获取定价计划的代码部分,一切都会正常工作。

reactjs next.js next.js13 nextjs14
1个回答
0
投票

我已经使用此解决方法解决了此错误:

isDynamicServerError
。我从这篇文章中复制了解决方案: 动态服务器使用:页面无法静态渲染,因为它在 Next.js 版本 14 中使用了 `nextUrl.searchParams`

export const getMeAction = async () => {
  try {
    const res = await fetch(`${process.env.BACKEND_BASE}/users/me`, {
      cache: 'no-store',
      headers: { ...getAuthorizationHeader() },
      next: { tags: [getCacheKey('userData')] },
    });
    if (!res.ok) {
      throw new Error('server_error');
    }
    const { data } = await res.json();
    return { success: data as UserType };
  } catch (err) {
    /** NOTE
     * This is a workaround
     * For the issue of next.js not being able to render the page statically
     * This issue arises in the pricing page
     * https://stackoverflow.com/questions/78010331/dynamic-server-usage-page-couldnt-be-rendered-statically-because-it-used-next
     **/
    if (isDynamicServerError(err)) {
      throw err;
    }
    return { error: 'server_error' };
  }
};

但是我的问题又是,为什么这个错误只在这个页面中出现,因为我还有其他页面,我在其中调用相同的服务器操作,但我没有在那里得到这个错误

import DashboardProperitesMain from '@/components/pages/DashboardProperitesPage';
import UserCtxLayoutProvider from '@/components/ui/UserCtxLayoutProvider';
import { PropertiesStatusFilterEnum } from '@/config';
import { Roles } from '@/schemas';
import { getMeAction } from '@/server/auth-actions';
import { redirectBaseOnRole } from '@/server/helper';
import { UserType } from '@/types';

export default async function DashboardHome({
  searchParams,
}: {
  searchParams?: {
    page?: string;
    status?: PropertiesStatusFilterEnum;
  };
}) {
  const currentPage = Number(searchParams?.page) || 1;
  const userData = (await getMeAction())?.success;
  redirectBaseOnRole(userData, [
    Roles.ADMIN,
    Roles.LANDLORD,
    Roles.SUB_USER,
    Roles.AGENT,
  ]);
  return (
    <UserCtxLayoutProvider userData={userData}>
      <DashboardProperitesMain
        userData={userData as UserType}
        currentPage={currentPage}
        status={searchParams?.status}
      />
    </UserCtxLayoutProvider>
  );
}

主要:

import React from 'react';

import { Suspense } from 'react';
import TableWrapper from '@/components/pages/DashboardProperitesPage/TableWrapper';
import Header from '@/components/pages/DashboardProperitesPage/Header';
import { DashboardProperitesTableSkelton } from '@/components/ui/DashboardPropertiesTable';
import { UserType } from '@/types';
import { PropertiesStatusFilterEnum } from '@/config';
type Props = {
  currentPage: number;
  userData: UserType | undefined;
  status?: PropertiesStatusFilterEnum;
};
export default function DashboardProperitesMain({
  currentPage,
  userData,
  status,
}: Props) {
  return (
    <section className=' max-w-[1300px] mx-auto '>
      <Header />
      <Suspense
        key={`${currentPage}-${status}`}
        fallback={<DashboardProperitesTableSkelton />}
      >
        <TableWrapper
          status={status}
          userData={userData}
          currentPage={currentPage}
        />
      </Suspense>
    </section>
  );
}

餐桌包装:

import React from 'react';
import {
  getAllProperitesAction,
  getMyProperitesAction,
} from '@/server/property-actions';
import { DashboardPropertiesTable } from '@/components/ui/DashboardPropertiesTable';
import { UserType } from '@/types';
import { Roles } from '@/schemas';
import { PropertiesStatusFilterEnum } from '@/config';
type Props = {
  currentPage: number;
  userData: UserType | undefined;
  status?: PropertiesStatusFilterEnum;
};
export default async function TableWrapper({
  currentPage,
  userData,
  status,
}: Props) {
  let properitesData;

  if (userData?.role === Roles.ADMIN) {
    properitesData = await getAllProperitesAction(
      currentPage,
      status
    );
  } else {
    properitesData = await getMyProperitesAction(currentPage, status);
  }

  return (
    <DashboardPropertiesTable
      data={properitesData.data}
      totalDocs={properitesData.totalDocs}
      currentPage={currentPage}
    />
  );
}

© www.soinside.com 2019 - 2024. All rights reserved.