当前位置:首页 > 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如何销毁

react如何销毁

React 组件销毁的机制 在 React 中,组件的销毁通常由 React 的生命周期管理。当组件从 DOM 中移除时,React 会自动触发销毁相关的生命周期方法。以下是关键点: 组件的销毁通常…

react如何更新

react如何更新

更新 React 版本的方法 检查当前 React 版本 运行以下命令查看项目中安装的 React 版本: npm list react 更新 React 及相关依赖 通过 npm 或 yarn…

react如何拓展

react如何拓展

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

react如何开发

react如何开发

React 开发基础步骤 安装 Node.js 和 npm/yarn 确保系统已安装 Node.js(包含 npm)或 Yarn。React 项目依赖这些工具管理包和运行脚本。官方推荐使用 Node.…

react如何同步

react如何同步

React 同步状态管理方法 在 React 中实现同步状态管理,可以通过以下多种方式实现: 使用 useState 和 useEffect 钩子 通过 useState 定义状态,使用 useEf…

react如何循环

react如何循环

循环渲染列表 在React中循环渲染列表通常使用map方法,这是最常用的方式。通过map可以将数组中的每个元素转换为React元素并渲染到页面上。 const items = ['Apple', '…