别再为 React 中的数据获取而苦恼 (React Day 7)

发布: (2026年1月15日 GMT+8 12:30)
6 min read
原文: Dev.to

Source: Dev.to

请提供您想要翻译的具体文本内容(文章正文),我将为您翻译成简体中文。
(代码块、URL 和 Markdown 语法会保持原样不变。)

Fetch 基础

原生的 fetch API 已内置于浏览器中,并且使用 Promise 进行工作。

Axios 概述

Axios 是一个流行的 HTTP 客户端,提供了自动 JSON 解析、更好的错误处理、请求取消和拦截器等便利功能。

import axios from 'axios';

axios.get('https://api.example.com/data')
  .then(res => console.log(res.data))
  .catch(err => console.error(err));

Fetch 与 Axios

功能FetchAxios
大小内置(额外 0 KB)大约 13 KB(已压缩)
JSON 处理手动 (res.json())自动
错误处理仅网络错误网络错误 + HTTP 状态码(例如 404)
取消请求需要 AbortController内置取消令牌
适用场景快速原型需要认证、拦截器的生产应用

当你需要全局认证头、请求/响应拦截器或更健壮的错误处理时,请使用 Axios。

常见加载/错误模式

import { useState, useEffect } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then(res => {
        if (!res.ok) throw new Error('Fetch failed!');
        return res.json();
      })
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, []);

  if (loading) return <div>Loading…</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <>
      {data?.map(post => (
        <div key={post.id}>- {post.title}</div>
      ))}
    </>
  );
}

管理加载 UI

  • loadingtrue 时显示旋转加载图标或骨架屏。
  • error 被设置时显示友好的错误信息。

useEffect 数据获取模式

场景依赖数组描述
挂载时获取[]首次渲染后运行一次。
依赖变化时重新获取[userId]每当 userId 变化时再次运行。
卸载时清理返回函数中止未完成的请求或取消订阅。

使用 AbortController 的中止示例

useEffect(() => {
  const controller = new AbortController();

  fetch('https://api.example.com/data', { signal: controller.signal })
    .then(res => res.json())
    .then(setData)
    .catch(err => {
      if (err.name !== 'AbortError') setError(err);
    });

  return () => controller.abort();
}, []);

陷阱: 省略依赖数组会导致 effect 在每次渲染时运行,进而产生无限的获取循环。

实际场景

天气应用 (Axios)

useEffect(() => {
  axios.get('https://api.openweathermap.org/data/2.5/weather', {
    params: { q: 'Bengaluru', appid: process.env.REACT_APP_OWM_KEY }
  })
  .then(res => setWeather(res.data))
  .catch(setError);
}, []);

无限滚动列表

  • 当用户滚动接近底部时获取更多页面。
  • 将新项目追加到现有状态,而不是替换。
  • 通过跟踪当前页码来防止重复条目。

常见问题与解决方案

问题原因解决办法
数据重复缺少页面跟踪存储并递增页面计数器。
无限循环useEffect 中缺少依赖数组添加适当的依赖项([][var])。
内存泄漏卸载时未进行清理在清理函数中中止请求或取消订阅。
闭包陈旧省略了依赖项在依赖数组中包含所有外部变量或使用函数式状态更新。
竞争条件请求重叠使用 AbortController 或 Axios 取消令牌取消之前的请求。
开发环境双重请求React StrictMode 会运行两次 effect接受这仅在开发时出现;确保清理工作正常。

性能技巧

  • Debounce 在触发获取之前对快速输入变化进行防抖。
  • 使用 IntersectionObserver 在无限滚动中实现懒加载。
  • Cache 结果使用 React QuerySWR 等库,以避免不必要的网络调用。
  • 在可能的情况下 Batch 多个请求。
  • 通过 CDN 提供资源并启用 compression(gzip/Brotli)。

安全提醒

切勿将 API 密钥提交到源代码管理。将它们存储在环境变量(process.env.REACT_APP_...)中,并在运行时引用。

高级主题(简要概述)

  • Error Boundaries – 将组件包装起来,以捕获因获取失败而导致的渲染错误。
  • React Suspense – 使用 “ 实现面向未来的加载状态。
  • Testing – 使用 MSWjest-fetch-mock 模拟网络调用。
  • Caching Strategies – 使用 stale‑while‑revalidate 模式实现快速 UI 更新。

进一步学习

  • 视频教程:Data Fetching in React(在 YouTube 上搜索以获取完整的演练)。

您现在已经拥有了在 React 中获取数据的坚实基础——从基本的 fetch 调用到使用 Axios 的健壮模式、加载状态、清理以及性能考虑。尝试构建一个 GitHub 用户搜索器或任何基于 API 的功能,以巩固这些概念。祝编码愉快!

Back to Blog

相关文章

阅读更多 »

React 编码挑战:卡片翻转游戏

React 卡片翻转游戏 – 代码 tsx import './styles.css'; import React, { useState, useEffect } from 'react'; const values = 1, 2, 3, 4, 5; type Card = { id: numb...