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判断逻辑错误问题
原代码存在两处错误:
- 语法错误:
Cookies.get("userImage" === undefined)应为Cookies.get("userImage") === undefined; - 数据解析错误:
setuserImage(JSON.parse(Cookies.get("user")))应解析userImageCookie而非userCookie。
修正后的完整判断逻辑
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
相关产品推荐
相关产品推荐

