关于RTK Query错误结构及多查询状态(isLoading、error)合并的技术咨询
Great questions! Let's break this down step by step, starting with how RTK Query structures errors, then moving to merging states for multiple queries in your custom hook.
First, let's clarify what RTK Query's error objects look like and where they come from.
What the Error Object Contains
RTK Query uses the FetchBaseQueryError type (for the default fetchBaseQuery) which has two main variants:
- HTTP status code errors: These have a numeric
statusproperty (like 400, 404, 500) and adatafield holding the raw error payload your API returns (e.g., a JSON object withmessageorerrorsfields). - Network/parsing errors: These have a string
statuslike'FETCH_ERROR'(network connection issues) or'PARSING_ERROR'(failed to parse API response), plus anerrorproperty with a human-readable message (e.g., "Failed to connect to server" or "Invalid JSON response").
Examples of each variant:
// HTTP 400 error from API const httpError: FetchBaseQueryError = { status: 400, data: { message: "Invalid user ID", errors: ["id must be a number"] } }; // Network connectivity error const networkError: FetchBaseQueryError = { status: "FETCH_ERROR", error: "Failed to reach the server" };
Where Errors Come From
These error objects are automatically generated by RTK Query:
- For non-2xx HTTP responses, it wraps the API's error body into the
datafield. - For network failures or parsing issues, it creates an error object with the appropriate string
statusand descriptive message inerror.
You don't need to manually define this base structure, but you can customize error handling (like transforming messages) using thetransformErrorResponseoption in your API slice.
Now let's refine your custom hook to properly merge loading, error, and data states—and handle error merging cleanly.
Full Custom Hook Implementation
Here's how to adjust your hook to collect and merge errors, plus handle loading/error states correctly:
import { useUsersQuery, useHousesQuery } from "./yourApiSlice"; type MergedError = { source: "users" | "houses"; } & FetchBaseQueryError; const useUsersAndHousesQueries = () => { const users = useUsersQuery(); const houses = useHousesQuery(); // Merge loading states: true if either query is in progress const isLoading = users.isLoading || houses.isLoading; // Merge error states: true if either query has failed const isError = users.isError || houses.isError; // Combine data from both queries const data = { users: users.data, houses: houses.data }; // Merge errors: collect all existing errors with their source context const errors: MergedError[] = []; if (users.error) { errors.push({ source: "users", ...users.error }); } if (houses.error) { errors.push({ source: "houses", ...houses.error }); } // Optional: Create a combined error message for quick UI display const errorMessage = errors.map(err => { if (err.status === "FETCH_ERROR" || err.status === "PARSING_ERROR") { return `${err.source}: ${err.error}`; } return `${err.source}: ${(err.data as any)?.message || `HTTP ${err.status}`}`; }).join(", "); return { isLoading, isError, data, errors, // Array of detailed errors with source context errorMessage, // Combined string for easy warning display // Optional: Pass through useful helper states/methods isSuccess: users.isSuccess && houses.isSuccess, refetch: () => Promise.all([users.refetch(), houses.refetch()]) }; };
Key Details About Error Merging
- Adding a
sourcefield lets your component identify which query failed—critical for targeted debugging or user-facing messages. - The
errorsarray preserves the full RTK Query error structure, so you can access status codes, raw API error payloads, etc., if needed. - The
errorMessageis optional but handy for quickly displaying a unified warning in your UI (adjust the formatting to match your app's design).
Bonus Tips
- If you only need to know if there's an error (not the specifics), you can just return
isErrorand let components check theerrorsarray for details. - For more complex parallel query scenarios, you could use RTK Query's
batchutility, but your custom hook approach is perfect for simple side-by-side queries.
内容的提问来源于stack exchange,提问作者Jordan Renaud

