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

React网站出现Maximum call stack size exceeded错误求助

问题分析与修复

根本原因

你遇到的栈溢出问题,核心是**useSelector每次都返回新对象**,导致useEffect的依赖photos永远在变化,触发无限循环:

  • 你用{ ...state.data }在useSelector里创建了新对象,组件每次渲染都会生成一个全新的引用
  • 这个新引用会触发依赖为photos的useEffect执行
  • useEffect里调用setImgList更新本地状态,导致组件重新渲染
  • 重新渲染又会生成新的photos对象,循环往复直到栈溢出

修复方案

方案1:直接引用Redux状态,避免创建新对象

既然你只是取state.data,没必要用扩展运算符克隆,直接返回原引用即可——Redux状态是 immutable 的,只有数据真的变化时引用才会更新:

import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { fetchDataHandler } from "./store/actions";

const PhotoWrapper = () => {
  const dispatch = useDispatch();
  const [imgList, setImgList] = useState([]);
  // 直接返回state.data,不创建新对象
  const photos = useSelector((state) => state.data);

  useEffect(() => {
    dispatch(fetchDataHandler());
  }, [dispatch]);

  useEffect(() => {
    const topImages = photos[0]?.map((photo) => (
      <img src={photo?.url} alt={photo?.title} key={photo.id} />
    ));
    setImgList(topImages);
  }, [photos]);

  return <div>{imgList}</div>;
};

export default PhotoWrapper;

⚠️ 注意:给img元素加上key属性,避免React警告。

方案2:如果需要转换状态结构,使用浅比较

如果确实需要对Redux状态做结构转换(比如只取部分字段),可以用Redux提供的shallowEqual函数,让useSelector比较对象内容而非引用:

import { useEffect, useState } from "react";
import { useDispatch, useSelector, shallowEqual } from "react-redux";
import { fetchDataHandler } from "./store/actions";

const PhotoWrapper = () => {
  const dispatch = useDispatch();
  const [imgList, setImgList] = useState([]);
  // 使用shallowEqual做浅比较
  const photos = useSelector((state) => ({ ...state.data }), shallowEqual);

  useEffect(() => {
    dispatch(fetchDataHandler());
  }, [dispatch]);

  useEffect(() => {
    const topImages = photos[0]?.map((photo) => (
      <img src={photo?.url} alt={photo?.title} key={photo.id} />
    ));
    setImgList(topImages);
  }, [photos]);

  return <div>{imgList}</div>;
};

export default PhotoWrapper;

方案3:去掉本地状态,直接在渲染时处理

其实你完全不需要本地状态imgList,直接在渲染阶段处理photos即可,减少不必要的状态和useEffect:

import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { fetchDataHandler } from "./store/actions";

const PhotoWrapper = () => {
  const dispatch = useDispatch();
  const photos = useSelector((state) => state.data);

  useEffect(() => {
    dispatch(fetchDataHandler());
  }, [dispatch]);

  return (
    <div>
      {photos[0]?.map((photo) => (
        <img src={photo?.url} alt={photo?.title} key={photo.id} />
      ))}
    </div>
  );
};

export default PhotoWrapper;

这个方案最简洁,也从根源上避免了循环问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 08:30:44