ReactJS路由到Profile页面时Cookie的role值被设为undefined问题
问题根因
你提供的登录逻辑中存在2个核心的时序和数据处理错误,是导致Cookie的role值被覆盖为undefined的直接原因:
- 登录接口返回数据的处理逻辑错误:你用
map遍历res.data写入Cookie,默认接口返回的是用户数组,但常规登录接口只会返回单个当前登录的用户对象。如果后端实际返回的是单个对象而非数组,调用map会遍历对象的键,导致写入Cookie时data变量为undefined,所有字段都会被写为undefined - 异步逻辑时序错误:
Promise.allSettled本身是异步的,你既没有await它,也没有把跳转、更新login状态的逻辑放到它的回调链里,导致页面跳转、父组件状态刷新的时候,Cookie还没完成写入,甚至出现写入到一半就跳转的情况,读写不同步就会读到undefined
另外还有一个隐藏风险点:你在写完Cookie后立刻调用Cookies.get读值判断跳转,js-cookie的写入虽然是同步的,但如果是遍历写入多次的场景,也会出现读到中间状态的问题,完全可以直接用接口返回的data判断,没必要走Cookie读。
修复方案
第一步:先确认接口返回结构
在axios的then回调里加一行日志打印console.log('接口返回数据:', res.data, typeof res.data, Array.isArray(res.data)),确认返回的是数组还是单个对象:
- 如果是单个对象,删掉
map遍历逻辑,直接取字段写入Cookie即可 - 如果确实是数组,加个判断取第一个有效用户写入,避免遍历多项覆盖Cookie
第二步:修正异步时序
把跳转、更新login状态的逻辑都放到Promise.allSettled的回调里,确保所有Cookie写入完成后再执行后续操作。
修复后核心代码示例
// 仅修改axios.then内的逻辑部分即可 axios.post(API_PATH, formData) .then(async (res) => { // 加async支持内部await if (res.data == false) { enqueueSnackbar('用户名或密码错误,请重试', {variant: 'error'}); return } if (validateJSON(res.data) !== true) { enqueueSnackbar(res.data, {variant: 'error'}); return } console.log('接口返回数据:', res.data) // 先处理数据:如果是数组取第一项,否则直接用返回对象 const userData = Array.isArray(res.data) ? res.data[0] : res.data if (!userData?.user_id) { enqueueSnackbar('登录失败,用户数据无效', {variant: 'error'}); destroyCookies() return } // 一次性写入所有Cookie 不需要多余的map遍历 Cookies.set("user_id", userData.user_id); Cookies.set("profile_image", userData.profile_image); Cookies.set("username", userData.username); Cookies.set("password", userData.password); Cookies.set("email", userData.email); Cookies.set("first_name", userData.first_name); Cookies.set("last_name", userData.last_name); Cookies.set("phone_number", userData.phone_number); Cookies.set("dob", userData.dob); Cookies.set("role", userData.role); Cookies.set("status", userData.status); Cookies.set("registered_date", userData.registered_date); Cookies.set("gender", userData.gender); // 直接用返回的userData判断跳转 不需要重复读Cookie enqueueSnackbar("登录成功", {variant: 'success'}); if (userData.role === "0" || userData.role === "2") { history.push('/dashboard'); } else if (userData.role === "1") { history.push('/profile'); } else { history.push('/dashboard'); } setLogin(prev => prev + 1) }) .catch((err) => { enqueueSnackbar(err, {variant: 'error'}); throw Error("登录流程出错:" + err); });
额外排查项
如果修复后还有问题,检查Profile页面的挂载/更新逻辑:
- 编辑个人资料接口如果没有返回
role字段,不要直接把接口返回的所有字段全量写入Cookie,会把缺失的role覆盖为undefined - 检查有没有全局路由守卫逻辑,在跳转的时候误操作了Cookie
内容的提问来源于stack exchange,提问作者ME MYSELF
相关产品推荐
相关产品推荐

