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

登录后跳转用户页,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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 06:27:10