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

如何在getServerSideProps中更优地获取RTK Query结果?

Optimizing RTK Query Usage in getServerSideProps (with Full Type Safety)

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

  1. No Redundant Code: We eliminate the Promise.all(api.util.getRunningOperationPromises()) call because initiate's promise already waits for the mutation to finish.
  2. Full Type Safety: The mutationResult object is fully typed by RTK Query — data matches your ApiCallResponse type, and error uses RTK Query's built-in error types (no more unknown!).
  3. 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 initiate to 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 dispatch gives you everything you need.

内容的提问来源于stack exchange,提问作者André Krosby

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 21:52:52