异步组件
本课属于 Coddy React 学习旅程的“Next.js 基础”单元。第 23 课,共 47 课。
这是上一章所做准备带来的成果。服务器组件可以是 async:
import { getDishes } from '../lib/data';
export default async function Page() {
const dishes = await getDishes();
return <h1>{dishes.length} dishes</h1>;
}再读一遍,因为这确实是个新概念。这个组件会等待。Next.js 会在服务器上运行它,让 await 执行完毕,然后才把结果转换成 HTML。
把它和你原本会编写的纯浏览器版本比较一下:
- 页面最初会呈现为空白
- 页面加载之后才会发出请求
- 某些状态发生变化,内容随之出现,用户每次都会看到闪烁
使用异步服务器组件时,不会先渲染空内容。没有内容会闪烁着出现,因为构建 HTML 时数据已经就绪。不需要 useEffect,不需要加载标记,也不需要第二次请求。
有两条规则可以让这种写法合法:
- 只有服务器组件可以使用
async:标记为'use client'的组件不可以 - 数据必须来自服务器能够访问的地方:数据库、文件,或像
lib/data.js这样的模块
挑战
简单lib/data.js 已提供并锁定。它会导出 getDishes(),该函数会返回一个 Promise,其中包含由 { id, name } 对象组成的数组。
- 将
app/page.jsx中的Page改为async函数。 - 使用
await getDishes(),并将结果存入dishes变量。 - 在
<ul id="dish-list">内,为每道菜渲染一个<li>,并设置key={dish.id}、id={dish.id},再将这道菜的name作为文本内容。
不要使用 useEffect,不要设置加载标记,只需使用 await。
亲手试试
import './globals.css';
export const metadata = {
title: 'My App',
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
</body>
</html>
);
}这节课包含一个小测验。开始学习即可作答,并记录你的进度。