如何正确地在Next页面组件之间传递Props?

起因

最近在写 Next (v14 App Router)时,发现运行 next build 出现了以下错误:

python 复制代码
Linting and checking validity of types ...Failed compile.
"src/app/home/updatelog/bugfix/page.tsx" has an invalid "default" export: Type "{ type: number; }" is not valid.

查看报错是在 Next 进行类型检查时出现的,根据给出的文件路径查看相关文件:

tsx 复制代码
// updatelog/bugfix/page.tsx

export default function BugFixPage({ type }: { type: number }) {
  return <div>...</div>;
}

发现组件定义并没有错,而且传入的参数的类型也没写错。

但报错却出现了 export: Type "{ type: number; }" is not valid. ,试着取消传递参数,再重新 build 时,发现就没报错了。

在其父文件中,是这样定义的:

tsx 复制代码
// updatelog/page.tsx

export default function UpdateLogPage() {
  const [updatePage, setUpdatePage] = useState<string>("/home/updatelog/newfeature")

  const renderContent = () => {
    switch (updatePage) {
      // 这样的做法是错误的❌
      case "/home/updateLog/newfeature":
        return <NewFeature type={0} />;
      case "/home/updateLog/bugfix":
        return <BugFixPage type={1} />;
      default:
        break;
    }
  }

  ...
}

溯源

由于 Next 的路由是基于文件系统的,也就是说每个页面都是一个单独的组件文件,当然这里说的"每个页面"指的是在 pages 目录下或者 app 目录下的页面。正是由于这样的特点,Next 就不能像传统的 SPA 应用一样在组件之间传递 Props 了。但这并不是说 Next 的页面组件不能接受参数,它可以接受参数,但并不能像 SPA 应用一样可以接收从另一个组件传递过来的参数。

要在 Next 中的页面之间传递属性,可以通过 getStaticPropsgetServerSidePropsfetch 等数据获取方法

getStaticProps

仅限 Pages Router 模式下才能使用

如果需要在构建时使用 Props ,则可以使用 getStaticProps 方法,它是在构建时运行的服务端函数,并返回一个对象,该对象作为 Props 传递给组件。

tsx 复制代码
import type { GetStaticProps } from "next";

export const getStaticProps: GetStaticProps = async (context) => {
  const res = await fetchAPI("...");

  return {
    props: {
      result: res.data,
    },
  };
};

export default function ResultPage({ result }) {
  return (
    <div>
      {result.map((item) => {
        <div key={item.id}>{item}</div>;
      })}
    </div>
  );
}

getServerSideProps

仅限 Pages Router 模式下才能使用

如果需要在请求时使用 Props ,可以使用 getServerSideProps 方法,它也是一个服务端函数,但会针对每个请求运行。

tsx 复制代码
import type { GetServerSideProps } from "next";

export const getServerSideProps: GetServerSideProps = async () => {
  const res = await fetchAPI("...");

  return {
    props: {
      result: res.data,
    },
  };
};

export default function ResultPage({ result }) {
  return (
    <div>
      {result.map((item) => {
        <div key={item.id}>{item}</div>;
      })}
    </div>
  );
}

fetch

在 App Router 模式下,可以直接 fetch 来获取数据

Next 扩展了原生的 fetch Web API ,额外添加了 配置缓存重新验证行为

可以在 服务器组件(Server Component)路由处理程序(页面目录的API路由)服务器操作(Server Action,在服务器上执行的异步函数)

tsx 复制代码
async function getData() {
  const res = await fetch("...", {
    // 配置缓存
    cache: 'force-cache',
    // 重新验证行为
    next: {
      revalidate: 3600
    },
  })

  return res.json()
}

export default async function FetchPage() {
  const data = await getData()

  return (
    <div>
      {data.map(i => {
        <div key={i}>{i}</div>
      })}
    </div>
  )
}

希望给遇到同样错误的同学一个思路。

相关推荐
NiNg_1_2345 分钟前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若12343 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~1 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语2 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport2 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg2 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww2 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_748254882 小时前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
星就前端叭3 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234523 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js