本文基于Next.js 15。API可能随版本升级变化,请同时参考官方文档。
本篇介绍实际服务中常见的三种请求模式:
并行
、
顺序
和
条件
请求,也会说明需要在客户端组件中获取数据时可以采用哪些方式。
需要同时请求多份数据时,使用
并行fetch
通常更高效。可以通过JavaScript的
Promise.all()实现。
export default async function Page() {
const [postsRes, usersRes] = await Promise.all([
fetch('https://jsonplaceholder.typicode.com/posts'),
fetch('https://jsonplaceholder.typicode.com/users'),
]);
const posts = await postsRes.json();
const users = await usersRes.json();
return (
<>
<h2>Posts</h2>
<ul>
{posts.map((post: any) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
<h2>Users</h2>
<ul>
{users.map((user: any) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</>
);
}
两个请求会
同时执行
,因此相比顺序执行,可以更快获得结果。
如果后一个请求需要以前一个请求的结果作为参数,就必须
按顺序
发送请求。
export default async function Page() {
const userRes = await fetch('https://jsonplaceholder.typicode.com/users/1');
const user = await userRes.json();
const postsRes = await fetch(
`https://jsonplaceholder.typicode.com/posts?userId=${user.id}`
);
const posts = await postsRes.json();
return (
<>
<h2>{user.name}의 게시글</h2>
<ul>
{posts.map((post: any) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</>
);
}
先获取用户ID,再请求与该ID相关的数据时,就适合采用这种方式。
有时需要
根据条件
决定是否请求数据,例如只有特定参数存在时才发起请求。
export default async function Page({ searchParams }: { searchParams: { userId?: string } }) {
let posts = [];
if (searchParams.userId) {
const res = await fetch(
`https://jsonplaceholder.typicode.com/posts?userId=${searchParams.userId}`
);
posts = await res.json();
}
return (
<>
<h2>게시글 목록</h2>
{posts.length > 0 ? (
<ul>
{posts.map((post: any) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
) : (
<p>게시글이 없습니다.</p>
)}
</>
);
}
如上所示,可以根据searchParams有条件地获取数据。
有些数据无法通过服务器组件处理,需要在客户端获取。这时可以使用React的useEffect,或者SWR等Hook库。
'use client';
import { useEffect, useState } from 'react';
export default function Page() {
const [posts, setPosts] = useState<any[]>([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then((res) => res.json())
.then(setPosts);
}, []);
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
useEffect在组件挂载后执行,因此需要向用户短暂显示“加载中”状态。
SWR是一个让React数据获取更加方便的Hook,默认提供缓存、重新获取和错误处理等能力。
'use client';
import useSWR from 'swr';
const fetcher = (url: string) => fetch(url).then((res) => res.json());
export default function Page() {
const { data, error, isLoading } = useSWR(
'https://jsonplaceholder.typicode.com/posts',
fetcher
);
if (isLoading) return <p>로딩 중입니다...</p>;
if (error) return <p>데이터를 불러오는 데 실패했습니다.</p>;
return (
<ul>
{data.map((post: any) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
SWR内部提供智能缓存与同步,有助于改善用户体验。
本篇介绍了三种实用的
fetch模式
:并行、顺序和条件请求,以及客户端数据获取方式。尤其是SWR,对客户端组件很有帮助,值得熟悉。
下一篇继续介绍
fetch自定义、缓存失效,以及通过路由处理器进行数据通信。
- 哪些场景适合并行fetch,哪些适合顺序fetch?
- 从客户端获取数据时,SEO方面需要注意什么?