react如何封装fetch
封装 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;
}
};
添加请求拦截和响应拦截
扩展封装以支持拦截器模式,便于全局处理请求和响应:

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,便于在组件中使用:

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>;
};






