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

React组件刷新后state内用户信息丢失问题求助

问题分析与解决方案

刷新页面后组件会重新挂载,user state回到初始的undefined状态,而axios请求是异步操作,在请求完成前组件就尝试调用user.map,直接抛出Cannot read properties of undefined (reading 'map')错误。同时你把单个用户对象存入数组的操作完全没必要,直接存储用户对象更合理。

核心修复步骤:

  1. 初始化合理的默认state
    将user的初始值设为null(匹配后端返回的单个用户对象格式),避免初始状态为undefined:

    const [user, setUser] = useState(null)
    
  2. 添加条件渲染/可选链操作
    在渲染时先判断user是否存在,再访问其属性,防止报错:

    // 可选链写法
    <textarea placeholder={user?.email} />
    // 或者带加载提示的条件判断
    <textarea placeholder={user ? user.email : "加载中..."} />
    
  3. 优化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])
    
  4. 完善错误处理
    请求失败时(比如用户未登录、后端返回错误),及时导航到登录页或给出提示,避免组件一直处于异常状态。

修改后的完整组件代码:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:15:33