You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Query中如何按状态码及错误键条件处理错误?

React Query 错误处理详解(含表单场景)

首先你代码里的核心问题是queryFn的传递方式错误:useQuery的第二个参数必须是一个返回Promise的函数,而你直接调用了getUserById(id),这会导致该函数立即执行,且React Query无法识别它作为合法的queryFn,所以才会出现“Missing queryFn”错误,同时onError也不会触发。

第一步:修复QueryFn

先把代码改成正确的形式:

const onError = (error) => {
    console.log('error occurred', error)
}
let { id } = useParams()
const { data: User, isLoading, isError, error, isRefetching, status, refetch } = useQuery(
    ['get-user-by-id', id], 
    // 用箭头函数包裹,确保queryFn是一个函数,且每次id变化时重新执行
    () => getUserById(id), 
    { onError }
)

第二步:确保API请求抛出带详细信息的错误

React Query只能捕获queryFn中抛出的错误,所以你的getUserById函数需要正确解析服务器返回的错误,并抛出包含状态码、错误信息的对象。

示例1:使用Axios的情况

Axios会自动将非2xx状态码的响应封装在error.response里,你可以直接抛出完整错误对象:

async function getUserById(id) {
    try {
        const response = await axios.get(`/api/users/${id}`);
        return response.data;
    } catch (err) {
        throw err;
    }
}

示例2:使用原生Fetch的情况

Fetch不会自动把非2xx状态码视为错误,需要手动判断并抛出自定义错误:

async function getUserById(id) {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) {
        const errorData = await response.json();
        throw {
            status: response.status,
            message: errorData.message || errorData.detail || '请求失败',
            fields: errorData.fields || null // 存储表单字段级错误
        };
    }
    return response.json();
}

第三步:在React Query中处理错误

现在错误能被正确捕获了,不管是在onError回调里,还是组件中通过error对象,都可以提取状态码和详细信息:

在onError中处理

const onError = (error) => {
    // Axios错误结构
    const status = error.response?.status;
    const errorMessage = error.response?.data?.message || error.response?.data?.detail || '未知错误';
    
    // Fetch自定义错误结构
    // const status = error.status;
    // const errorMessage = error.message;

    console.log(`错误状态码:${status},错误信息:${errorMessage}`);
    
    if (status === 404) {
        alert('用户不存在');
    } else if (status === 400) {
        alert(`参数错误:${errorMessage}`);
    }
}

在组件中渲染错误信息

if (isError) {
    let errorContent = '请求出错';
    const status = error.response?.status || error.status;
    
    if (status === 404) {
        errorContent = '找不到该用户';
    } else if (status === 400) {
        // 处理表单字段级错误
        const fieldErrors = error.response?.data?.fields || error.fields;
        if (fieldErrors) {
            return (
                <div className="field-errors">
                    {Object.entries(fieldErrors).map(([field, msg]) => (
                        <p key={field}>{field}:{msg}</p>
                    ))}
                </div>
            );
        }
        errorContent = error.response?.data?.message || error.response?.data?.detail;
    }
    
    return <div className="error">{errorContent}</div>;
}

表单场景的进阶处理

对于表单提交(比如用useMutation),逻辑完全通用,只需把useQuery换成useMutation,将字段错误同步到表单状态即可:

const { mutate, isError, error } = useMutation(
    (formData) => axios.post('/api/register', formData),
    {
        onError: (err) => {
            if (err.response?.status === 400 && err.response.data.fields) {
                // 同步到表单状态管理(如React Hook Form)
                setFieldErrors(err.response.data.fields);
            }
        }
    }
);

内容的提问来源于stack exchange,提问作者rediet yosef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 02:55:30