当前位置:首页 > React

react如何封装fetch

2026-02-26 01:46:52React

封装 fetch 的基本方法

在 React 中封装 fetch 通常涉及创建一个可复用的函数,处理请求和响应逻辑。以下是一个基础封装示例:

const fetchData = async (url, options = {}) => {
  try {
    const response = await fetch(url, {
      headers: {
        'Content-Type': 'application/json',
        ...options.headers,
      },
      ...options,
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    return await response.json();
  } catch (error) {
    console.error('Fetch error:', error);
    throw error;
  }
};

添加请求拦截和响应拦截

扩展封装以支持拦截器模式,便于全局处理请求和响应:

react如何封装fetch

const createFetch = (baseUrl = '') => {
  const interceptors = {
    request: [],
    response: [],
  };

  const fetchInstance = async (url, options) => {
    let modifiedUrl = baseUrl + url;
    let modifiedOptions = { ...options };

    interceptors.request.forEach(interceptor => {
      const result = interceptor(modifiedUrl, modifiedOptions);
      modifiedUrl = result.url || modifiedUrl;
      modifiedOptions = result.options || modifiedOptions;
    });

    const response = await fetch(modifiedUrl, modifiedOptions);

    let modifiedResponse = response;
    interceptors.response.forEach(interceptor => {
      modifiedResponse = interceptor(modifiedResponse);
    });

    return modifiedResponse;
  };

  fetchInstance.interceptors = {
    request: {
      use: (interceptor) => interceptors.request.push(interceptor),
    },
    response: {
      use: (interceptor) => interceptors.response.push(interceptor),
    },
  };

  return fetchInstance;
};

封装为自定义 Hook

将封装逻辑转换为 React Hook,便于在组件中使用:

react如何封装fetch

import { useState, useEffect, useCallback } from 'react';

const useFetch = (initialUrl, initialOptions = {}) => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);

  const fetchData = useCallback(async (url, options) => {
    setLoading(true);
    try {
      const response = await fetch(url, {
        headers: {
          'Content-Type': 'application/json',
          ...initialOptions.headers,
          ...options?.headers,
        },
        ...initialOptions,
        ...options,
      });

      if (!response.ok) throw new Error(response.statusText);
      const json = await response.json();
      setData(json);
    } catch (err) {
      setError(err);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    if (initialUrl) fetchData(initialUrl, initialOptions);
  }, [fetchData, initialUrl, initialOptions]);

  return { data, error, loading, fetchData };
};

处理取消请求

添加 AbortController 支持以取消未完成的请求:

const useFetchWithAbort = (initialUrl, initialOptions = {}) => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);
  const abortControllerRef = useRef(new AbortController());

  const fetchData = useCallback(async (url, options) => {
    abortControllerRef.current.abort();
    abortControllerRef.current = new AbortController();

    setLoading(true);
    try {
      const response = await fetch(url, {
        signal: abortControllerRef.current.signal,
        ...initialOptions,
        ...options,
      });

      if (!response.ok) throw new Error(response.statusText);
      const json = await response.json();
      setData(json);
    } catch (err) {
      if (err.name !== 'AbortError') setError(err);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    if (initialUrl) fetchData(initialUrl, initialOptions);
    return () => abortControllerRef.current.abort();
  }, [fetchData, initialUrl, initialOptions]);

  return { data, error, loading, fetchData };
};

类型化封装(TypeScript)

使用 TypeScript 增强类型安全:

interface FetchOptions extends RequestInit {
  params?: Record<string, string>;
}

const typedFetch = async <T>(
  url: string,
  options: FetchOptions = {}
): Promise<T> => {
  const { params, ...restOptions } = options;
  const queryString = params ? new URLSearchParams(params).toString() : '';
  const fullUrl = queryString ? `${url}?${queryString}` : url;

  const response = await fetch(fullUrl, {
    headers: {
      'Content-Type': 'application/json',
      ...restOptions.headers,
    },
    ...restOptions,
  });

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  return response.json() as Promise<T>;
};

标签: reactfetch
分享给朋友:

相关文章

react如何diff

react如何diff

React Diff 算法原理 React 的 Diff 算法是 Virtual DOM 的核心部分,用于高效更新真实 DOM。其核心思想是通过对比新旧 Virtual DOM 树的差异,最小化 DO…

react 如何调试

react 如何调试

调试 React 应用的方法 使用 React Developer Tools 安装 Chrome 或 Firefox 的 React Developer Tools 扩展,可以检查组件树、状态和 p…

react如何拓展

react如何拓展

React 拓展方法 使用高阶组件(HOC) 高阶组件是一种复用组件逻辑的方式,通过接收一个组件并返回一个新组件实现功能拓展。例如,为组件添加日志功能: function withLoggin…

react 如何启动

react 如何启动

创建 React 项目 使用官方工具 create-react-app 快速初始化项目,需提前安装 Node.js(版本 ≥ 14.0.0)和 npm/yarn: npx create-react…

如何构建react

如何构建react

构建 React 项目的步骤 安装 Node.js 和 npm 确保系统已安装 Node.js(包含 npm)。可通过命令行验证: node -v npm -v 使用 Create React Ap…

如何恢复react

如何恢复react

恢复 React 项目的方法 检查并修复依赖项 运行 npm install 或 yarn install 重新安装所有依赖项。如果依赖项损坏或缺失,这将恢复项目所需的库和工具。 恢复删除的文件…