使用fetch时,如何在react-query中正确定义自定义错误类型?
React Query useQuery 实现类型安全的自定义 Fetch 错误方案
如果你用原生 Fetch 想给 useQuery 做类型正确的自定义错误,同时让 React Query 自动推断类型(不手动指定泛型),可以按下面的步骤来:
1. 定义带状态码的自定义错误类
先搞一个继承自 Error 的类,专门存响应状态码和相关信息,保证类型明确:
class FetchError extends Error { constructor( message: string, public status: number, public response?: Response ) { super(message); this.name = 'FetchError'; // 修复原型链,保证 instanceof 判断准确 Object.setPrototypeOf(this, FetchError.prototype); } }
2. 封装类型安全的 Fetch 请求函数
把 Fetch 逻辑封装成一个函数,请求失败(非 2xx 状态)时抛出上面的自定义错误,同时指定返回数据的类型:
async function fetchJson<T>(url: string): Promise<T> { const res = await fetch(url); if (!res.ok) { // 读取响应里的错误信息,没有的话用状态码提示 const errorMsg = await res.text() || `请求失败,状态码:${res.status}`; throw new FetchError(errorMsg, res.status, res); } // 解析 JSON 并指定返回类型 T return res.json() as Promise<T>; }
这里的泛型 T 用来定义接口返回的数据结构,请求出错时抛出的 FetchError 会被 React Query 自动捕获,类型也会跟着推断出来。
3. 在 useQuery 里直接用,自动推断错误类型
现在用这个封装好的函数写 useQuery,不用手动指定泛型,React Query 会自动识别错误类型是 FetchError,你可以直接在 useErrorBoundary 里访问 status:
// 先定义你的数据类型 type UserData = { id: number; username: string; email: string; }; const { data, isLoading, error } = useQuery( ['user-data'], () => fetchJson<UserData>('https://api.example.com/user'), { useErrorBoundary: (err) => { // 这里 err 自动推断为 FetchError,直接用 status 没问题 return err.status >= 500; } } ); // 如果要在组件里处理错误,也能安全访问 status if (error instanceof FetchError) { console.log('错误状态码:', error.status); }
额外处理网络层面的错误
如果要处理 Fetch 本身失败的情况(比如断网、域名不存在),可以在封装函数里加 try/catch:
async function fetchJson<T>(url: string): Promise<T> { try { const res = await fetch(url); if (!res.ok) { const errorMsg = await res.text() || `请求失败,状态码:${res.status}`; throw new FetchError(errorMsg, res.status, res); } return res.json() as Promise<T>; } catch (err) { // 处理网络错误,给个状态码 0 标识 if (err instanceof Error) { throw new FetchError(err.message, 0); } throw new FetchError('未知错误', 0); } }
这样不管是 HTTP 错误还是网络错误,抛出的都是类型明确的 FetchError,React Query 都能正确推断,你在任何错误处理逻辑里都能安全访问 status 属性。
内容的提问来源于stack exchange,提问作者hcode
相关产品推荐
相关产品推荐

