React中dispatch无限触发、无法获取数据报最大更新深度超出错误
问题根因
你遇到的死循环、数据undefined问题是两处核心写法错误导致的:
useEffect缺失依赖数组,触发无限渲染循环- Redux异步逻辑写法错误,加上状态字段不匹配,导致读不到接口数据
1. 无限循环报错原因
你写的useEffect没有传入第二个参数(依赖数组),React默认会在组件每一次渲染完成后都执行effect回调。
回调里执行dispatch(fetching(1))会更新Redux状态,状态变更会触发组件重新渲染,渲染完成后又会执行effect再次dispatch,形成「渲染→dispatch→更新→渲染」的死循环,最终触发React的最大更新深度限制报错。
2. itemsList为undefined的原因
这里有三个叠加错误:
- Redux Toolkit的reducer必须是纯函数,绝对不能在reducer里直接写异步请求(axios.get)。你现在直接把axios返回的Promise对象赋值给了state,根本没有拿到接口返回的实际业务数据。
- 组件里
useSelector读取的是store.card下的itemsList字段,但你写的slice初始状态里只有log字段,从来没有定义过itemsList,自然读取结果为undefined。 - 接口URL拼接写法错误:
${page = payload.payload}是赋值表达式,不是正常的请求参数拼接格式,就算请求发出去参数也是错的。 - 额外的命名隐患:你定义的slice名叫
cartSlice,但组件里引入的路径是cardSlice,如果store里挂载的key和你读取的路径不匹配,也会读不到状态。
修复步骤
第一步:重写slice逻辑,用createAsyncThunk处理异步请求
Redux Toolkit的异步逻辑必须通过createAsyncThunk封装,不能直接写在同步reducer里:
import {createSlice, createAsyncThunk} from "@reduxjs/toolkit"; import axios from "axios"; // 封装异步请求action export const fetchList = createAsyncThunk('card/fetchList', async (page) => { // 正确拼接请求参数 const res = await axios.get(`http://localhost:5000/fetch/?page=${page}`) return res.data }) const initialState = { itemsList: [], // 定义组件要读取的itemsList字段 loading: false } const cardSlice = createSlice({ name: 'card', // 和store挂载的key、useSelector读取路径保持一致 initialState, reducers: {}, // 监听异步action的不同状态,更新对应state extraReducers: (builder) => { builder .addCase(fetchList.pending, (state) => { state.loading = true }) .addCase(fetchList.fulfilled, (state, action) => { state.loading = false state.itemsList = action.payload // 把接口返回的真实数据存入state }) .addCase(fetchList.rejected, (state) => { state.loading = false }) } }) export default cardSlice.reducer;
第二步:修正组件useEffect依赖
给useEffect传入空依赖数组,让请求只在组件首次挂载时执行一次,避免重复触发:
import React, {useEffect} from "react"; import {useDispatch, useSelector} from "react-redux"; // 引入封装好的异步action import {fetchList} from "../features/cardSlice"; import Cards from "./Cards"; export default function HomePage(){ const dispatch = useDispatch(); // 确认store里该slice挂载的key是card,和slice的name字段一致 const {itemsList} = useSelector((store) => store.card) console.log(itemsList) useEffect(()=>{ dispatch(fetchList(1)); }, []) // 空依赖=仅组件首次挂载时执行一次 function cardMapper(items) { return( <Cards name = {items.name} key = {items.id} cuisine={items.cuisine} address={items.address} /> ) } return( <div> {itemsList.map(cardMapper)} </div> ) }
注意:修改后确认你的Redux store配置里,该slice挂载的key为
card,和代码里的读取路径、slice的name字段完全匹配,否则还是会出现读不到状态的问题。
内容的提问来源于stack exchange,提问作者Jay Kumar
相关产品推荐
相关产品推荐

