如何将数据请求函数迁移至Redux Toolkit的Reducer中?
将异步请求逻辑迁移至Redux Toolkit
1. 改造Redux Slice(storage.ts)
Redux reducer本身不能处理异步操作,所以要用Redux Toolkit提供的createAsyncThunk封装请求逻辑,同时在slice里处理请求的三种状态(加载中、成功、失败),顺便把组件里的状态统一移到Redux中。
更新后的storage.ts代码:
import { createSlice, PayloadAction, createAsyncThunk } from '@reduxjs/toolkit' import { IProducts } from '../components/Products/products.interface' // 封装异步请求逻辑为thunk export const fetchProducts = createAsyncThunk( 'products/fetchProducts', async ({ page = 1, id }: { page?: number; id?: number }, { rejectWithValue }) => { const itemsPerPage = 5 let url: string if (id) { url = `https://reqres.in/api/products/${id}` } else { url = `https://reqres.in/api/products?per_page=${itemsPerPage}&page=${page}` } try { const response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json' }, }) if (!response.ok) { const errorData = await response.json() throw new Error(errorData.message || response.status.toString()) } const data = await response.json() // 统一单个产品和列表的返回格式 if (id) { return { page: 1, per_page: 1, total: 1, total_pages: 1, data: [data.data], } as IProducts } return data as IProducts } catch (error) { return rejectWithValue((error as Error).message) } } ) // 扩展状态类型,加入加载和错误状态 type ProductsState = { list: IProducts loading: boolean error: string | null } const initialState: ProductsState = { list: { data: [{ id: 0, name: '', year: 0, color: '', pantone_value: '' }], page: 0, per_page: 0, total: 0, total_pages: 0, }, loading: false, error: null, } const ProductsSlice = createSlice({ name: 'products', initialState, reducers: { // 可选:手动清空错误状态的同步action clearError(state) { state.error = null }, }, // 处理异步thunk的三种状态 extraReducers: (builder) => { builder // 请求发起时:标记加载中,清空错误 .addCase(fetchProducts.pending, (state) => { state.loading = true state.error = null }) // 请求成功时:更新产品列表,结束加载 .addCase(fetchProducts.fulfilled, (state, action: PayloadAction<IProducts>) => { state.loading = false state.list = action.payload }) // 请求失败时:记录错误信息,结束加载 .addCase(fetchProducts.rejected, (state, action) => { state.loading = false state.error = action.payload as string }) }, }) export const { clearError } = ProductsSlice.actions export default ProductsSlice.reducer
2. 修改Main.tsx中的调用逻辑
现在组件里不用再写复杂的请求逻辑,直接dispatch定义好的异步thunk就行,加载状态、错误信息都从Redux里取,不用组件自己维护。
示例代码:
import { useDispatch, useSelector } from 'react-redux' import { fetchProducts } from './path/to/storage' import { RootState } from './path/to/store' // 需提前定义RootState类型 // 组件内部逻辑 const dispatch = useDispatch() const { list, loading, error } = useSelector((state: RootState) => state.products) // 触发请求的函数 const getProducts = (page = 1, id?: number) => { dispatch(fetchProducts({ page, id })) } // 渲染时根据状态展示不同内容 if (loading) return <div>加载中...</div> if (error) return <div>出错了:{error}</div> // 渲染产品列表...
关键改动说明
- 用
createAsyncThunk封装异步逻辑:这是Redux Toolkit官方推荐的方式,自动生成请求中、成功、失败三种状态的action,不用手动写重复代码。 - 统一状态管理:把组件里的加载、错误状态移到Redux中,避免组件内部状态分散混乱。
- 标准化数据格式:在thunk里提前处理单个产品的返回结构,保证组件拿到的数据格式统一,简化渲染逻辑。
- 集中错误处理:通过
rejectWithValue传递错误信息,在slice里统一处理失败状态,组件直接读取即可。
内容的提问来源于stack exchange,提问作者Yevhenii
相关产品推荐
相关产品推荐

