【Next.js】Next.js 数据获取

Next.js 提供了多种灵活的数据获取方式,适应不同场景下的需求,包括服务端渲染(SSR)、静态生成(SSG)、增量静态再生(ISR)和客户端渲染(CSR)。以下是详细说明及代码示例:


一、服务端数据获取

1. 静态生成(SSG)

在构建时生成页面,适用于内容不频繁变化的页面(如博客、文档、产品页)。

基本用法getStaticProps
在构建时获取数据并生成静态页面。

// pages/blog.js
export async function getStaticProps() {
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();
  return { props: { posts } };
}

export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

动态路由 + SSGgetStaticPaths
生成动态路由的静态页面(如 /posts/[id].js)。

// pages/posts/[id].js
export async function getStaticPaths() {
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();
  const paths = posts.map((post) => ({ params: { id: post.id } }));
  return { paths, fallback: false }; // fallback: 'blocking' 或 true
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`);
  const post = await res.json();
  return { props: { post } };
}

增量静态再生(ISR)
在运行时按需重新生成静态页面。

export async function getStaticProps() {
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();
  return { props: { data }, revalidate: 60 }; // 每60秒最多重新生成一次
}

2. 服务端渲染(SSR)

每次请求时生成页面,适合实时数据(如用户仪表盘)。

getServerSideProps
在每次请求时运行,生成动态内容。

// pages/user.js
export async function getServerSideProps(context) {
  const { req, res } = context;
  const user = await getUser(req); // 从请求中获取用户信息
  return { props: { user } };
}

export default function UserProfile({ user }) {
  return <div>{user.name}</div>;
}

二、客户端数据获取

适用于无需 SEO 或用户交互后加载数据的场景(如搜索框、分页)。

1. 使用 useEffect + fetch

在组件挂载后或依赖变化时获取数据。

// components/UserList.js
import { useState, useEffect } from 'react';

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch('/api/users')
      .then((res) => res.json())
      .then((data) => setUsers(data));
  }, []);

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}
2. 使用数据请求库(如 SWR、React Query)

优化客户端请求(缓存、重试、自动刷新)。

// 使用 SWR
import useSWR from 'swr';

function Profile() {
  const { data, error } = useSWR('/api/user', fetcher);

  if (error) return <div>Failed to load</div>;
  if (!data) return <div>Loading...</div>;

  return <div>Hello {data.name}!</div>;
}

三、混合渲染策略

结合服务端和客户端数据获取,优化用户体验。

示例:首屏静态渲染 + 客户端更新
  1. 使用 getStaticProps 生成静态内容。
  2. 客户端获取实时数据并更新。
// pages/dashboard.js
export async function getStaticProps() {
  const staticData = await fetch('https://api.example.com/static-data');
  return { props: { staticData } };
}

function Dashboard({ staticData }) {
  const [realTimeData, setRealTimeData] = useState(null);

  useEffect(() => {
    fetch('/api/real-time')
      .then((res) => res.json())
      .then((data) => setRealTimeData(data));
  }, []);

  return (
    <div>
      <h1>{staticData.title}</h1>
      <p>Real-time: {realTimeData?.value}</p>
    </div>
  );
}

四、API Routes

在 Next.js 中直接创建后端 API,简化全栈开发。

// pages/api/user.js
export default function handler(req, res) {
  const user = { name: 'Alice', id: 1 };
  res.status(200).json(user);
}

客户端调用:

fetch('/api/user')
  .then((res) => res.json())
  .then((data) => console.log(data));

五、Next.js 13+ App Router 的新特性

app 目录下,支持在组件中直接使用 async/await 获取数据。

// app/page.js
async function getData() {
  const res = await fetch('https://api.example.com/data');
  return res.json();
}

export default async function Page() {
  const data = await getData();
  return <div>{data.title}</div>;
}

六、选择策略的对比

方法适用场景优点缺点
getStaticProps (SSG)内容固定的页面(如博客、文档)极快的加载速度,SEO 友好构建时生成,不适合频繁更新
getServerSideProps (SSR)需要实时数据的页面(如用户仪表盘)实时数据,SEO 友好每次请求都需服务器处理,速度较慢
客户端获取用户交互后加载数据(如搜索、分页)减少服务端压力,灵活首屏加载慢,不利于 SEO
ISR需要定期更新的静态内容(如电商商品页)结合静态生成和动态更新首次访问可能需等待再生

七、最佳实践

  1. 优先使用 SSG/ISR:除非必须实时数据,否则优先静态生成。
  2. 按需混合渲染:首屏使用 SSG/SSR,客户端加载附加数据。
  3. 缓存 API 请求:通过 revalidate 或 CDN 减少重复请求。
  4. 错误处理:客户端和服务端均需处理加载状态和错误。
  5. 性能优化:使用 next/image 优化图片,next/link 预加载路由。

掌握这些方法后,可根据业务需求灵活选择数据获取策略,兼顾性能、SEO 和用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值