React组件刷新后state内用户信息丢失问题求助
问题分析与解决方案
刷新页面后组件会重新挂载,user state回到初始的undefined状态,而axios请求是异步操作,在请求完成前组件就尝试调用user.map,直接抛出Cannot read properties of undefined (reading 'map')错误。同时你把单个用户对象存入数组的操作完全没必要,直接存储用户对象更合理。
核心修复步骤:
初始化合理的默认state
将user的初始值设为null(匹配后端返回的单个用户对象格式),避免初始状态为undefined:const [user, setUser] = useState(null)添加条件渲染/可选链操作
在渲染时先判断user是否存在,再访问其属性,防止报错:// 可选链写法 <textarea placeholder={user?.email} /> // 或者带加载提示的条件判断 <textarea placeholder={user ? user.email : "加载中..."} />优化axios请求逻辑
无需每次请求都创建新的axios实例,直接在请求配置中添加withCredentials即可;改用async/await让代码更简洁易读:useEffect(() => { const fetchUser = async () => { try { const res = await axios.get(`http://127.0.0.1:3000/users/getMe`, { withCredentials: true }) // 直接存储用户对象,不需要放入数组 setUser(res.data.data.user) } catch (error) { console.error("获取用户信息失败:", error) // 未登录或请求失败时导航到登录页 navigate("/login", { replace: true }) } } fetchUser() }, [navigate])完善错误处理
请求失败时(比如用户未登录、后端返回错误),及时导航到登录页或给出提示,避免组件一直处于异常状态。
修改后的完整组件代码:
import axios from "axios"; import React, { useEffect, useState } from "react"; import { useNavigate } from 'react-router-dom' import './account.css' function Account(props) { const [user, setUser] = useState(null) const [currentPass, setCurrentPass] = useState("") const [newPass, setNewPass] = useState("") const [confirmPass, setConfirmPass] = useState("") const navigate = useNavigate(); useEffect(() => { const fetchUser = async () => { try { const res = await axios.get(`http://127.0.0.1:3000/users/getMe`, { withCredentials: true }) setUser(res.data.data.user) } catch (error) { console.error("获取用户信息失败:", error) navigate("/login", { replace: true }) } } fetchUser() }, [navigate]) const updatePassword = async (e) => { e.preventDefault() try { const res = await axios.patch(`http://127.0.0.1:3000/users/updatePassword`, { currentPassword: currentPass, newPassword: newPass, passwordConfirm: confirmPass }, { withCredentials: true }); console.log(res.data.data.user) navigate("/", { replace: true }); } catch (error) { console.error("更新密码失败:", error); } } return ( <div className="account-container" > <div className="title-container"> <p className="title">My Account</p> </div> <p className="sub-title">User information </p> <form className="form-user-information"> <div className="div-form-user-information"> <label className="label-form-user-information">Username</label> <textarea placeholder={user?.username || "加载中..."} /> </div> <div className="div-form-user-information"> <label className="label-form-user-information">Email</label> <textarea placeholder={user?.email || "加载中..."} /> </div> <div className="div-form-user-information"> <label className="label-form-user-information">First name</label> <textarea placeholder={user?.firstName || "加载中..."} /> </div> <div className="div-form-user-information"> <label className="label-form-user-information">Last name</label> <textarea placeholder={user?.lastName || "加载中..."} /> </div> </form> <div className="buttom-line"></div> {/* //////CONTACT INFORMATION////////// */} <p className="sub-title-contact">CONTACT INFORMATION </p> <form className="form-contact-information"> <div className="div-form-contact-information"> <label className="label-form-contact-information">Full Address</label> <textarea placeholder={user?.address || "加载中..."} /> </div> <div className="div-form-contact-information"> <label className="label-form-contact-information">City</label> <textarea placeholder={user?.city || "加载中..."} /> </div> <div className="div-form-contact-information"> <label className="label-form-contact-information">Country</label> <textarea placeholder={user?.country || "加载中..."} /> </div> <div className="div-form-contact-information"> <label className="label-form-contact-information">Postal code</label> <textarea placeholder={user?.postalCode || "加载中..."} /> </div> </form> <div className="buttom-line-contact"></div> {/* //////PASSWORD INFORMATION////////// */} <p className="sub-title-password">UPDATE PASSWORD </p> <form className="form-password-information"> <div className="div-form-password-information"> <label className="label-form-password-information">Current Password</label> <textarea onChange={(e) => setCurrentPass(e.target.value)} placeholder="Current Password..." value={currentPass} /> </div> <div className="div-form-password-information"> <label className="label-form-password-information">New Password</label> <textarea onChange={(e) => setNewPass(e.target.value)} placeholder="New Password..." value={newPass} /> </div> <div className="div-form-password-information"> <label className="label-form-password-information">Confirm Password</label> <textarea onChange={(e) => setConfirmPass(e.target.value)} placeholder="Confirm Password..." value={confirmPass} /> </div> <button onClick={(e) => updatePassword(e)} className="btn-update-pass">Update password</button> </form> </div> ); } export default Account;
额外优化建议:
- 给密码输入框添加
value属性,转为受控组件,符合React状态管理规范; - 表单输入建议使用
input标签(type="text"/type="password")替代textarea,更符合语义化要求。
内容的提问来源于stack exchange,提问作者elyasaf
相关产品推荐
相关产品推荐

