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

React组件两类报错:短时间内Location/History调用过多及更新深度超限

解决React组件的最大更新深度和Location API调用过多问题

问题根源分析

1. 最大更新深度警告

第二个useEffect依赖包含isOpen,调用onOpen()会更新isOpen状态,触发组件重新渲染,导致该useEffect再次执行。初始状态下agency设为[],会直接进入onOpen()分支触发状态更新,加上fetch完成后agency变化再次触发useEffect,形成渲染循环隐患。

2. Location API调用过多报错

如果fetch返回的data.agency为null,useEffect会执行redirect,触发路由导航导致组件卸载重挂载,重新fetch后仍得到agency为null,再次触发redirect,形成无限导航循环,短时间内多次调用History API引发报错。

修复方案

步骤1:修正状态初始值与判断逻辑

将agency初始值从[]改为null,确保仅在fetch完成后执行判断逻辑,避免初始阶段误触发分支。

步骤2:防止无限导航循环

用useRef标记是否已执行过redirect,避免重复触发导航。

步骤3:优化依赖与逻辑

移除不必要的useMemo,直接使用agency作为useEffect依赖;添加useRef标记是否已打开modal,防止重复调用onOpen()。

修改后的代码

const OwnerPage = () => {
  const onOpen = useAgencyModal((state) => state.onOpen);
  const isOpen = useAgencyModal((state) => state.isOpen);
  const params = useParams();
  const [owner, setOwner] = useState<User | null>(null);
  // 修正初始值为null,匹配后续判断逻辑
  const [agency, setAgency] = useState<any | null>(null);
  // 标记是否已执行过redirect
  const hasRedirected = useRef(false);
  // 标记是否已打开过modal
  const hasOpenedModal = useRef(false);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(`/api/owner/${params.ownerId}`, {
          method: "GET",
        });
        const data = await response.json();
        setAgency(data.agency);
        setOwner(data.owner);
      } catch (error) {
        console.error("Error occurred while fetching data:", error);
      }
    };
    fetchData();
  }, [params.ownerId]);

  useEffect(() => {
    // 数据未加载完成时不执行逻辑
    if (agency === null && owner === null) return;

    if (agency !== null) {
      // 仅在modal未打开且未触发过打开操作时调用onOpen
      if (!isOpen && !hasOpenedModal.current) {
        onOpen();
        hasOpenedModal.current = true;
      }
    } else {
      // 仅在未执行过redirect时触发导航
      if (!hasRedirected.current) {
        hasRedirected.current = true;
        redirect(`/dashboard/owner/${params.ownerId}/dashboard`);
      }
    }
  }, [agency, owner, isOpen, onOpen, params.ownerId]);

  return null;
};

额外说明

  • 移除冗余的useMemo,直接使用agency和owner作为依赖,简化代码且不影响性能。
  • useRef标记状态不会触发组件重渲染,有效避免依赖变化导致的重复执行问题。
  • 增加数据加载完成判断,确保逻辑仅在fetch返回结果后执行,消除初始阶段的误触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:57:04