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

React登录中嵌套Axios请求致用户图片加载异常的解决方法

React登录Hook及页面逻辑问题解决方案

1. Base64图片加载延迟问题

Base64格式体积偏大,直接作为img的src会导致加载缓慢。可以将Base64转换为Blob对象,再通过URL.createObjectURL生成本地临时URL,提升加载效率,同时通过缓存避免重复转换。

修改useGetUserImage.js

import axios from "axios";
import Cookies from "js-cookie";

const useGetUserImage = () => {
  // Base64转Blob工具函数
  const base64ToBlob = (base64Data) => {
    const [typePart, dataPart] = base64Data.split(',');
    const mime = typePart.match(/:(.*?);/)[1];
    const byteString = atob(dataPart);
    const arrayBuffer = new ArrayBuffer(byteString.length);
    const uint8Array = new Uint8Array(arrayBuffer);
    
    for (let i = 0; i < byteString.length; i++) {
      uint8Array[i] = byteString.charCodeAt(i);
    }
    
    return new Blob([uint8Array], { type: mime });
  };

  const ImageFetchingHandler = ({ token }) => {
    axios({
      method: "post",
      url: `${process.env.REACT_APP_API_URL_API_FETCH_IMAGE}`,
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
        "DotNet-Timeout": 30000,
      },
      data: JSON.stringify({ id: "4" }),
    }).then((d) => {
      // 保留Base64到Cookie(Blob URL页面刷新会失效)
      Cookies.set("userImage", JSON.stringify(d.data), {
        path: "/",
        expires: 3,
        sameSite: "strict",
        secure: window.top.location.protocol === "https:",
      });
    });
  };

  return { ImageFetchingHandler };
};

export default useGetUserImage;

在mainpage.js中优化图片加载

用useMemo缓存转换后的Blob URL,避免重复计算:

import React, { useEffect, useMemo, useState } from "react";
import Cookies from "js-cookie";
import { useNavigate } from "react-router";

const MainPage = () => {
  const navigate = useNavigate();
  const [userImageBase64, setUserImageBase64] = useState(null);

  // 转换Base64为Blob URL并缓存
  const imageUrl = useMemo(() => {
    if (!userImageBase64) return null;
    const [typePart, dataPart] = userImageBase64.split(',');
    const mime = typePart.match(/:(.*?);/)[1];
    const byteString = atob(dataPart);
    const arrayBuffer = new ArrayBuffer(byteString.length);
    const uint8Array = new Uint8Array(arrayBuffer);
    
    for (let i = 0; i < byteString.length; i++) {
      uint8Array[i] = byteString.charCodeAt(i);
    }
    
    const blob = new Blob([uint8Array], { type: mime });
    return URL.createObjectURL(blob);
  }, [userImageBase64]);

  useEffect(() => {
    // 修正后的Cookie判断逻辑
    const userCookie = Cookies.get("user");
    const userImageCookie = Cookies.get("userImage");
    
    if (!userCookie || !userImageCookie) {
      navigate("/Login");
      return;
    }
    
    try {
      setUserImageBase64(JSON.parse(userImageCookie));
    } catch (e) {
      console.error("解析用户图片Cookie失败:", e);
      navigate("/Login");
    }
  }, [navigate]);

  return (
    <div>
      {/* 条件渲染+占位图,避免src为undefined报错 */}
      {imageUrl ? (
        <img 
          src={imageUrl} 
          alt="用户头像" 
          onLoad={() => URL.revokeObjectURL(imageUrl)} // 释放临时URL
        />
      ) : (
        <img 
          src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" 
          alt="加载中" 
        />
      )}
    </div>
  );
};

export default MainPage;

2. img标签src未加载完成报错问题

直接给img的src赋值undefined会触发报错,可通过两种方式解决:

  • 条件渲染:仅当图片数据存在时渲染img标签;
  • 设置默认占位图:给src配置一个小体积的Base64占位图(如上示例)。

3. mainpage.js Cookie判断逻辑错误问题

原代码存在两处错误:

  1. 语法错误:Cookies.get("userImage" === undefined) 应为 Cookies.get("userImage") === undefined;
  2. 数据解析错误:setuserImage(JSON.parse(Cookies.get("user"))) 应解析userImage Cookie而非user Cookie。

修正后的完整判断逻辑

React.useEffect(() => {
  const userCookie = Cookies.get("user");
  const userImageCookie = Cookies.get("userImage");
  
  // 检查两个Cookie是否都存在
  if (!userCookie || !userImageCookie) {
    navigate("/Login");
    return;
  }
  
  try {
    setuserImage(JSON.parse(userImageCookie));
  } catch (e) {
    console.error("用户图片Cookie解析失败", e);
    navigate("/Login");
  }
}, [navigate]);

额外修复:useLogin.js导航逻辑错误

原代码中无论登录成功与否,都会执行页面跳转,需将导航逻辑移至登录成功分支:

// 修改useLogin.js中的HandleLogin方法
const HandleLogin = (e) => {
  e.preventDefault();
  if (Boolean(userName) && Boolean(password)) {
    axios
      .post(`${process.env.REACT_APP_API_URL_API_LOGIN}`, {
        softWareOrUser: false,
        userName: userName,
        password: password,
      })
      .then((r) => {
        if (r.data.resCode === 1) {
          ImageFetchingHandler(r.data);
          cookieFn(r.data.Data);
          setSnack(false);
          // 仅登录成功时跳转
          navigate("/main");
        } else {
          setSnack(true);
        }
      })
      .catch((e) => {
        console.error("登录失败:", e.message);
        alert("登录失败,请检查账号密码");
      });
  } else {
    alert("请填写所有字段");
  }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 13:45:30