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
相关产品推荐
相关产品推荐

