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

如何将数据请求函数迁移至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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 06:35:19