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

React组件异步获取图片详情,页面导航时触发TypeError错误求助

问题成因与解决方案

报错成因

  1. 重试逻辑未随组件卸载终止:组件卸载时,你仅取消了当前正在进行的API请求,但之前通过setTimeout调度的重试请求仍会在1秒后执行。此时组件已卸载,后续发起的请求或状态更新操作会触发异常。
  2. Axios响应解构错误:你直接从axios.get的返回值中解构result,但Axios的响应对象本身并不包含result属性——接口返回的数据通常在响应对象的data字段中。这会导致result为undefined,访问result?.data自然会抛出Cannot read properties of undefined (reading 'data')错误。
  3. 取消请求的错误未区分处理:组件卸载调用source.cancel()后,正在进行的请求会进入catch块,但你未判断该错误是否为请求取消导致的Axios专属错误,直接打印错误日志,进而暴露了不必要的报错信息。

修复后的代码

import { useState, useEffect, useRef } from 'react';
import axios from 'axios';

const GridCard = ({ imageURL, id }) => {
  const [imageDetail, setImageDetail] = useState(imageURL);
  const source = axios.CancelToken.source();
  const timeoutRef = useRef(null);
  const isMounted = useRef(true);

  const getImageDetails = async () => {
    if (!isMounted.current) return; // 组件已卸载则终止执行
    try {
      // 正确解构Axios响应:接口返回数据在response.data中
      const response = await axios.get(`documents/${id}`, {
        cancelToken: source.token
      });
      // 假设接口返回结构为 { result: { data: { thumbViewLink } } },请根据实际接口调整
      const { result } = response.data;

      if (result?.data?.thumbViewLink === null) {
        // 保存定时器ID,方便后续清除
        timeoutRef.current = setTimeout(getImageDetails, 1000);
      } else {
        setImageDetail(result?.data?.thumbViewLink);
      }
    } catch (error) {
      // 仅在非主动取消请求的情况下打印错误
      if (!axios.isCancel(error)) {
        console.error("Error fetching image details", error);
      }
    }
  };

  useEffect(() => {
    if (imageDetail === null) {
      getImageDetails();
    }

    return () => {
      isMounted.current = false; // 标记组件已卸载
      source.cancel("Component unmounted"); // 取消当前请求
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current); // 清除重试定时器
      }
    };
  }, [imageDetail, id]);

  // 图片展示渲染逻辑
  return <div>{/* 此处添加图片展示代码 */}</div>;
};

export default GridCard;

关键修复点

  • 跟踪组件挂载状态:用useRef创建isMounted标记,在getImageDetails开头检查组件是否仍挂载,避免卸载后执行状态更新或请求操作。
  • 清除重试定时器:通过useRef保存setTimeout的ID,在组件卸载的清理函数中清除定时器,终止重试逻辑。
  • 修正响应解构:正确获取Axios响应中的接口数据,根据实际接口返回结构调整解构逻辑。
  • 区分取消请求错误:通过axios.isCancel(error)判断是否为主动取消的请求,避免打印无关错误日志。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:23:16