Next.js 如何优雅地获取远程服务端的数据

1,323 阅读3分钟

Next.js 是一个功能强大的 React 框架,支持服务器端渲染(SSR)和静态网站生成(SSG)。在使用它时,fetch 远程服务器数据是非常常见的操作。以下是一个详细的教程,教你如何优雅地完成这个任务。


教程目标

  • 了解如何在 Next.js 中使用 fetch 请求远程数据。
  • 学会处理 JSON 数据并解析。
  • 明确如何选择合适的数据获取方法(getServerSidePropsgetStaticProps)。
  • 掌握在组件中使用 useEffectfetch 的注意事项。

一、基础知识点

1.1 Next.js 数据获取方法

在 Next.js 中,有三种主要的数据获取方式:

  1. getStaticProps:用于静态生成页面时获取数据。
  2. getServerSideProps:用于在每次请求时获取数据(SSR)。
  3. 客户端数据获取:在组件中使用 fetch 请求数据(如 useEffect 中)。

每种方法适用于不同的场景:

  • 静态生成:适合数据不频繁变化的页面。
  • 服务器端渲染:适合需要实时更新数据的页面。
  • 客户端获取:适合在用户交互后需要加载数据的场景。

二、实现步骤

2.1 在 getStaticProps 中 Fetch 数据

场景:

你有一个博客页面,需要在构建时从远程服务器获取文章列表。

示例代码:

// pages/blog.js
export async function getStaticProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts');
  if (!res.ok) {
    throw new Error('Failed to fetch data');
  }
  const posts = await res.json();

  return {
    props: {
      posts, // 传递给页面组件的 props
    },
  };
}

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

知识点:

  1. fetch 的使用

    • fetch 默认是异步的,需要 await 获取结果。
    • 调用 res.json() 将返回的 JSON 数据解析为 JavaScript 对象。
  2. 错误处理

    • 检查 res.ok 来判断请求是否成功,失败时抛出错误。

2.2 在 getServerSideProps 中 Fetch 数据

场景:

你需要实时显示某个用户的最新信息。

示例代码:

// pages/user.js
export async function getServerSideProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/users/1');
  if (!res.ok) {
    return {
      notFound: true, // 返回 404 页面
    };
  }
  const user = await res.json();

  return {
    props: {
      user, // 传递给页面组件的 props
    },
  };
}

export default function UserPage({ user }) {
  return (
    <div>
      <h1>User Info</h1>
      <p>Name: {user.name}</p>
      <p>Email: {user.email}</p>
    </div>
  );
}

知识点:

  1. 实时数据

    • 每次请求页面都会运行 getServerSideProps
  2. 返回错误页面

    • 可以通过返回 notFound: true 告诉 Next.js 显示 404 页面。

2.3 在客户端组件中 Fetch 数据

场景:

用户点击按钮后加载更多内容。

示例代码:

import { useState, useEffect } from 'react';

export default function LoadMore() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);

  const fetchData = async () => {
    setLoading(true);
    try {
      const res = await fetch('https://jsonplaceholder.typicode.com/todos?_limit=5');
      if (!res.ok) {
        throw new Error('Failed to fetch');
      }
      const result = await res.json();
      setData(result);
    } catch (error) {
      console.error(error.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <h1>Load More Example</h1>
      <button onClick={fetchData} disabled={loading}>
        {loading ? 'Loading...' : 'Load Data'}
      </button>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
}

知识点:

  1. 状态管理

    • 使用 useState 管理数据和加载状态。
  2. 错误处理

    • 使用 try-catch 捕获错误并打印到控制台。

三、数据获取的最佳实践

  1. 处理错误

    • 确保捕获并处理 fetch 可能抛出的错误。
    • 提供友好的错误提示,例如展示 "无法加载数据"。
  2. 避免重复请求

    • getStaticPropsgetServerSideProps 中不需要重复请求同一个数据源。
  3. 缓存

    • 如果数据变化不频繁,可以在服务端启用缓存策略。
  4. 环境变量

    • 将 API URL 等配置保存在 .env 文件中:

      NEXT_PUBLIC_API_URL=https://jsonplaceholder.typicode.com
      

    在代码中使用:

    const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/posts`);
    
  5. 选择合适的获取方式

    • 如果数据静态化即可满足需求,优先选择 getStaticProps
    • 实时性要求高时,使用 getServerSideProps
    • 与用户交互触发的数据获取,适合客户端使用 fetch

四、总结

  • Next.js 提供多种数据获取方式,选择适合的方式非常重要。
  • 使用 fetch 时,需要注意错误处理和状态管理。
  • 环境变量和缓存策略是优化的关键。

以上方法覆盖了大部分数据获取场景,理解并应用这些知识后,你将能优雅地处理远程数据获取和 JSON 解析任务。