如何在getServerSideProps中更优地获取RTK Query结果?
Awesome question — let's clean up this RTK Query usage in getServerSideProps and fix those type gaps at the same time. The good news is RTK Query has built-in tools to make this way simpler and fully type-safe.
First: Ditch the Manual Mutation Lookup & Promise.all
Your current code manually searches the store's mutations and waits for all running operations, but RTK Query's initiate method returns a promise that resolves when the mutation completes (success or failure). That means you can cut out the redundant Promise.all and mutation lookup entirely.
Second: Leverage RTK Query's Auto-Generated Types
When you define your API slice with createApi, RTK Query automatically generates type definitions for your endpoints, mutation results, and state. Let's use those to eliminate unknown types.
Here's the Simplified, Type-Safe Implementation
First, make sure your API slice exports the necessary types and endpoint references (this is standard for RTK Query setups):
// apiSlice.ts import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; // Define your response and params types upfront type ApiCallResponse = { /* Your response structure here */ }; type ApiCallParams = { /* Your params structure here */ }; export const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: '/api' }), endpoints: (builder) => ({ apiCall: builder.mutation<ApiCallResponse, ApiCallParams>({ query: (params) => ({ url: '/your-endpoint', method: 'POST', body: params, }), }), }), }); // Export the endpoint for server-side use export const { endpoints: { apiCall } } = api; // Optional: Export root state type if you need to access store state directly export type RootState = ReturnType<typeof api.reducer>;
Now update your getServerSideProps to use the type-safe mutation result directly:
// Your page component file import { wrapper } from '../store'; // Your Redux wrapper import type { GetServerSideProps } from 'next'; import { apiCall } from '../apiSlice'; export const getServerSideProps: GetServerSideProps = wrapper.getServerSideProps( (store) => async (context) => { // Dispatch the mutation and await its completion const mutationResult = await store.dispatch( apiCall.initiate({ /* your params here */ }) ); // Handle errors with full type safety if (mutationResult.error) { // RTK Query's error type is either FetchBaseQueryError or SerializedError if ('status' in mutationResult.error) { const statusCode = mutationResult.error.status; // Type: number | "FETCH_ERROR" | "PARSING_ERROR" | "TIMEOUT_ERROR" if ('data' in mutationResult.error) { // Assert your custom error data type if needed const errorDetails = mutationResult.error.data as { error: string }; console.error('API error:', errorDetails.error); } // Example: Return 404 if status is 404 if (statusCode === 404) { return { notFound: true }; } } } // Access data with full type safety (matches ApiCallResponse) const fetchedData = mutationResult.data; return { props: { data: fetchedData, }, }; }, );
Why This Works Better
- No Redundant Code: We eliminate the
Promise.all(api.util.getRunningOperationPromises())call becauseinitiate's promise already waits for the mutation to finish. - Full Type Safety: The
mutationResultobject is fully typed by RTK Query —datamatches yourApiCallResponsetype, anderroruses RTK Query's built-in error types (no moreunknown!). - Cleaner Logic: Instead of digging through the store's mutation state to find your operation, you get the result directly from the dispatch call.
If You Do Need to Access Store State Directly
If for some reason you need to fetch the mutation state from the store later, use your typed root state to avoid unknown:
const rootState = store.getState(); const apiMutations = rootState.api.mutations; // Type-safe if RootState is correctly defined const apiCallMutation = Object.values(apiMutations).find( (m) => m?.endpointName === 'apiCall' ) as typeof apiCall.MutationState | undefined; if (apiCallMutation?.error) { // Error is fully typed here too }
Key Takeaways
- Always use the promise returned by
initiateto wait for server-side mutations — it's simpler and type-safe. - Leverage RTK Query's auto-generated types by defining your response/params upfront and exporting endpoint references.
- Avoid manual store state traversal unless absolutely necessary — the mutation result from
dispatchgives you everything you need.
内容的提问来源于stack exchange,提问作者André Krosby

