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

Redux Toolkit createAsyncThunk无返回值 useSelector取数报错

问题现象

在React项目中使用Redux Toolkit的createAsyncThunk搭配Axios处理异步请求,初期功能运行正常;仅调整SCSS相关代码后,Chrome控制台抛出TypeError: Cannot read properties of undefined (reading 'map')错误。全程未修改Redux与thunk相关逻辑,但出现两个异常:

  • useSelector无法获取对应store状态
  • 原本可正常响应的接口无返回

相关代码

thunk与slice定义

export const getTopBanners = createAsyncThunk(
    'home/getTopBanners',
    async ()=>{
        console.log('hello?');
        const response = await axiosGetTopBanner();
        console.log('res:'+response);
        return response.banners
    }
)

export const topBannerSlice = createSlice({
    name:'topBanner',
    initialState:{
        pics:[],
        isLoading:false
    },
    extraReducers:{
        [getTopBanners.pending]:(state)=>{
            state.isLoading = true;
        },
        [getTopBanners.fulfilled]:(state,action)=>{
            state.pics = action.payload;
            state.isLoading = false;
        },
        [getTopBanners.rejected]:(state)=>{
            state.isLoading = false;
        }
    }
})

组件使用代码

const dispatch = useDispatch();
// 此处无法获取到对应状态
const topBanners = useSelector((state) => state.topBanner.pics);
useEffect(() => {
    dispatch(getTopBanners());
  }, [dispatch]);

store配置代码

const store = configureStore({
  reducer:{
    topBanner:topBannerReducer,
    recommendData:recommendDataReducer
  }
})

问题排查与修复

这个报错和SCSS修改本身没有直接关联,是之前隐藏的写法问题在热更新/代码重载后触发了,按以下顺序排查即可:

  1. 修正extraReducers的写法
    你现在用的对象key映射action type的写法,是Redux Toolkit 1.x版本的兼容写法,RTK 2.0之后默认不再支持这种写法,必须用builder回调形式注册异步action的处理逻辑,否则thunk的pending/fulfilled/rejected三个状态都不会被slice正确监听,请求派发后状态不会更新,state.topBanner会直接变成undefined,组件里对topBanners调用map就会抛出你看到的错误。
    修正后的slice代码:
    export const topBannerSlice = createSlice({
        name:'topBanner',
        initialState:{
            pics:[],
            isLoading:false
        },
        extraReducers: (builder) => {
            builder
                .addCase(getTopBanners.pending, (state) => {
                    state.isLoading = true;
                })
                .addCase(getTopBanners.fulfilled, (state, action) => {
                    state.pics = action.payload;
                    state.isLoading = false;
                })
                .addCase(getTopBanners.rejected, (state) => {
                    state.isLoading = false;
                })
        }
    })
    
  2. 给异步请求加兜底逻辑
    现在的thunk逻辑没有错误捕获,一旦接口返回结构异常(比如response上没有banners字段),thunk会直接进入rejected状态,而rejected处理逻辑里没有给pics设置默认空数组,也会触发map的报错。可以给thunk加一层容错:
    export const getTopBanners = createAsyncThunk(
        'home/getTopBanners',
        async (_, { rejectWithValue }) => {
            try {
                const response = await axiosGetTopBanner();
                return response?.banners || [];
            } catch (err) {
                return rejectWithValue(err);
            }
        }
    )
    
  3. 检查Provider包裹层级
    如果调整SCSS的时候不小心改动了根组件的代码,确认下<Provider store={store}>是包裹在所有用到Redux状态的业务组件外层,没有出现组件在Provider外层渲染的情况,这种场景也会导致useSelector拿不到正确的store状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:45:59