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

