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

在createSlice的reducer中派发action的正确实现方法是什么?

createSlice中reducer内派发action的正确实现方案

错误原因

Redux要求所有reducer(包括extraReducers里的回调)必须是无副作用的纯函数,仅能根据传入的state和action计算返回新的state,不允许执行派发action、异步请求、修改外部变量等操作。你在getBusiness.fulfilled回调中直接调用getX()既不符合reducer的纯函数要求,也不会生效——此时getX()仅创建了action对象,没有实际触发派发流程。

另外你原有代码里的状态判断存在逻辑错误:if (!response.status == 200)会先计算!response.status再和200比较,永远不会触发异常抛出,需要修正为if (response.status !== 200)。


正确实现方案

有两种常用实现方式,可根据业务场景选择:

方案1:在createAsyncThunk内部派发(推荐,适用于getBusiness成功后必须触发getX的场景)

createAsyncThunk的payloadCreator函数第二个参数可以拿到thunkAPI对象,其中自带dispatch方法,可以直接在请求成功后派发getX:

import axios from 'axios';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

// 修改getBusiness的定义,接收thunkAPI参数
export const getBusiness = createAsyncThunk('business/getBusiness', async (_, thunkAPI) => {
  try {
    const response = await axios.get('https://api.github.com/users/mapbox')
    if (response.status !== 200) throw new Error(response.statusText)
    const data = response.data
    // 请求成功后直接派发getX
    thunkAPI.dispatch(getX())
    return data
  } catch (err) {
    // 抛出异常触发rejected状态
    return thunkAPI.rejectWithValue(err.message)
  }
});

export const getX = createAsyncThunk('business/getX', async () => {
  const response = await axios.get('https://my-json-server.typicode.com/typicode/demo/posts')
  if (response.status !== 200) throw new Error(response.statusText)
  return response.data
});

export default createSlice({
  name: 'business',
  initialState: {
    loading: false,
    error: '',
    data: [],
    test : []
  },
  reducers: {},
  // 原有extraReducers逻辑不需要改,删除之前的getX()调用即可
  extraReducers: {
    [getBusiness.pending]: (state) => {
      state.loading = true;
    },
    [getBusiness.rejected]: (state, action) => {
      state.loading = false;
      state.error = action.payload || action.error.message;
    },
    [getBusiness.fulfilled]: (state, action) => {
      state.loading = false;
      state.data = action.payload;
      // 删掉这里的getX()调用即可
    },
    [getX.pending]: (state) => {
      state.loading = true;
    },
    [getX.rejected]: (state, action) => {
      state.loading = false;
      state.error = action.payload || action.error.message;
    },
    [getX.fulfilled]: (state, action) => {
      state.loading = false;
      state.test = action.payload;
    }
  }
});

方案2:在组件触发侧派发(适用于仅特定场景下getBusiness成功才需要触发getX的场景)

如果getX的触发和业务组件的场景绑定,可以在组件中调用unwrap方法等待getBusiness执行完成后再派发getX:

import { useDispatch } from 'react-redux'
import { getBusiness, getX } from './businessSlice'

const BusinessComponent = () => {
  const dispatch = useDispatch()

  const handleFetch = async () => {
    try {
      // 等待getBusiness执行成功
      await dispatch(getBusiness()).unwrap()
      // 成功后再派发getX
      dispatch(getX())
    } catch (err) {
      console.error('请求失败:', err)
    }
  }

  return <button onClick={handleFetch}>获取业务数据</button>
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:36:03