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

如何在createSlice中使用RTK Query?需在切片中处理请求数据

在自定义Slice中处理RTK Query数据的解决方案

因为你需要在createSlice生成的自定义切片中处理RTK Query获取的数据,同时还要保留同步操作该数据的能力,而transformResponse仅能修改RTK Query缓存的数据,无法同步到自定义切片状态,以下是两种可行方案:

方案1:利用RTK Query的onQueryStarted钩子

在RTK Query的endpoint中配置onQueryStarted,在请求完成(成功/失败)时直接分发自定义切片的action,将请求数据同步到自定义状态中。这种方式直接绑定请求逻辑,简洁高效。

步骤1:给自定义切片添加处理数据的reducers

const initialState: ICurrencyState = {
  currencyRates: {},
  availableCurrencyOptions: [],
  fromCurrency: '',
  toCurrency: '',
  exchangeRate: 0,
  error: null
}

export const currencySlice = createSlice({
  name: 'currency',
  initialState,
  reducers: {
    setCurrencyRates: (state, action) => {
      state.currencyRates = action.payload.rates;
      state.availableCurrencyOptions = Object.keys(action.payload.rates);
    },
    setExchangeError: (state, action) => {
      state.error = action.payload;
    },
    // 新增同步操作的reducers示例
    setFromCurrency: (state, action) => {
      state.fromCurrency = action.payload;
    },
    setToCurrency: (state, action) => {
      state.toCurrency = action.payload;
    }
  }
})

export const { setCurrencyRates, setExchangeError, setFromCurrency, setToCurrency } = currencySlice.actions;

步骤2:修改RTK Query的endpoint,添加onQueryStarted

export const currencyApi = createApi({
  reducerPath: 'currencyApi',
  baseQuery: fetchBaseQuery({ baseUrl: 'https://api.apilayer.com/exchangerates_data' }),
  endpoints: (build) => ({
    fetchCurrencyRates: build.query<IApiResponse, string>({
      query: (currency) => ({
        url: '/latest',
        params: { base: currency },
        headers: { apikey: 'SomeApiKey' } // 替换为你的实际API Key
      }),
      async onQueryStarted(currency, { dispatch, queryFulfilled }) {
        try {
          const { data } = await queryFulfilled;
          dispatch(setCurrencyRates(data));
        } catch (error) {
          dispatch(setExchangeError(error instanceof Error ? error.message : '请求失败'));
        }
      }
    })
  })
})

export const { useFetchCurrencyRatesQuery } = currencyApi;

使用方式

在组件中调用useFetchCurrencyRatesQuery触发请求,请求完成后会自动更新自定义切片的状态:

import { useFetchCurrencyRatesQuery } from './currencyApi';
import { useDispatch, useSelector } from 'react-redux';
import { setFromCurrency } from './currencySlice';

function CurrencyComponent() {
  const { isLoading, error } = useFetchCurrencyRatesQuery('USD');
  const { availableCurrencyOptions, fromCurrency } = useSelector(state => state.currency);
  const dispatch = useDispatch();

  return (
    <div>
      {isLoading && <p>加载中...</p>}
      {error && <p>错误:{error}</p>}
      <select 
        value={fromCurrency}
        onChange={(e) => dispatch(setFromCurrency(e.target.value))}
      >
        {availableCurrencyOptions.map(curr => (
          <option key={curr} value={curr}>{curr}</option>
        ))}
      </select>
    </div>
  )
}

方案2:使用RTK的监听中间件(Listener Middleware)

如果需要全局监听多个RTK Query请求的结果,或希望请求逻辑与切片解耦,可以使用RTK的createListenerMiddleware监听RTK Query的完成action,再分发切片action同步数据。

步骤1:创建并配置监听中间件

import { createListenerMiddleware } from '@reduxjs/toolkit';
import { currencyApi } from './currencyApi';
import { setCurrencyRates, setExchangeError } from './currencySlice';

const listenerMiddleware = createListenerMiddleware();

// 监听请求成功的action
listenerMiddleware.startListening({
  matcher: currencyApi.endpoints.fetchCurrencyRates.matchFulfilled,
  effect: async (action, listenerApi) => {
    listenerApi.dispatch(setCurrencyRates(action.payload));
  }
});

// 监听请求失败的action
listenerMiddleware.startListening({
  matcher: currencyApi.endpoints.fetchCurrencyRates.matchRejected,
  effect: async (action, listenerApi) => {
    const errorMsg = action.error.message || '请求失败';
    listenerApi.dispatch(setExchangeError(errorMsg));
  }
});

// 注册到store
export const store = configureStore({
  reducer: {
    [currencyApi.reducerPath]: currencyApi.reducer,
    currency: currencySlice.reducer
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware()
      .concat(currencyApi.middleware)
      .concat(listenerMiddleware.middleware)
});

说明

这种方式无需修改RTK Query的endpoint,通过全局监听实现数据同步,适合复杂场景下的多请求统一处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 07:54:17