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

