登录后跳转用户页,Context API中userId显示undefined的问题求助
问题解决思路与代码修复
1. Context 中 userId 为 undefined 的核心原因
你的UseContextProvider依赖props传入userId,但跳转后的Profile页面并未将路由参数里的userId正确传递给它;若Context Provider挂载在更高层级(比如App.js),它也无法直接获取路由参数,自然会出现userId为undefined的情况。
修复方案:让Context直接从路由取userId
修改Context代码,直接通过useParams获取路由中的userId,无需依赖props传递:
import React, { useState, useEffect } from "react"; import axios from "axios"; import { createContext } from "react"; import { useParams } from 'react-router-dom'; export const UserContext = createContext({}); export function UseContextProvider({ children }) { const { userId } = useParams(); // 直接从路由提取userId const [user, setUser] = useState(null); useEffect(() => { // 仅当userId存在时才发起请求 if (!userId) return; const fetchUserDetails = async () => { try { // 从localStorage取出登录时保存的token,用于后端身份验证 const token = localStorage.getItem('token'); const response = await axios.get(`/auth/profile/${userId}`, { headers: { Authorization: `Bearer ${token}` // 符合后端中间件的token格式要求 } }); setUser(response.data.user); // 对应后端返回的{user: 用户信息}结构 } catch (error) { console.error("获取用户详情失败:", error); } }; fetchUserDetails(); }, [userId]); return ( <UserContext.Provider value={{ user, setUser }}> {children} </UserContext.Provider> ); }
2. 登录逻辑补充:保存token
后端返回了验证用的token,但前端未存储,导致后续请求无法通过身份验证。修改登录函数:
const loginUser = async (e) => { e.preventDefault(); const { email, password } = login; try { const response = await axios.post('/auth/login', { email, password, }); const { userId, token } = response.data; localStorage.setItem('token', token); // 将token存入localStorage setUserId(userId); console.log(`登录页获取到的userId: ${userId}`); // 修正错误判断逻辑,直接用后端返回的字段 if (response.data.error) { toast.error(response.data.error); } else { setLogin({}); toast.success('登录成功!欢迎回来'); navigate(`/auth/profile/${userId}`); } } catch (error) { console.error(error); toast.error('登录失败,请检查账号密码'); } };
3. 后端getProfile函数的严重bug修复
当前getProfile用User.findOne()会返回数据库第一个用户,而非当前登录用户。利用中间件已存入req.user的当前用户信息,直接返回即可:
const getProfile = async (req, res) => { try { if (!req.user) { return res.status(404).json({ message: '未找到用户' }); } // 移除敏感字段(如密码)后返回 const { password, ...safeUserInfo } = req.user._doc; return res.json({ user: safeUserInfo }); } catch (error) { return res.status(500).json({ error: error.message }); } };
4. 后端身份验证中间件优化
处理Authorization头的Bearer前缀,避免token解析失败:
const isAuthenticated = async (req, res, next) => { try { let token = req.headers.authorization; if (!token) { return res.status(401).json({ message: '未提供验证token' }); } // 提取Bearer前缀后的token内容 token = token.split(' ')[1]; jwt.verify(token, process.env.JWT_SECRET, async (err, decoded) => { if (err) { return res.status(401).json({ message: '无效的验证token' }); } if (decoded.exp < Date.now() / 1000) { return res.status(401).json({ message: '验证token已过期' }); } req.user = await User.findById(decoded.id); next(); }); } catch (error) { return next(error); } };
内容的提问来源于stack exchange,提问作者user22465814
相关产品推荐
相关产品推荐

