React+Node.js+MongoDB:登录后用户ID无法传递至个人页问题
问题描述
我正在开发一个支持账号创建的网站,需求如下:
- 未登录状态下显示登录按钮
- 登录后显示个人页按钮与登出按钮
- 点击个人页按钮需跳转至
/users/[用户ID]页面,用于修改个人简介和头像
技术栈采用React、Node.js Express、MongoDB。我尝试在UserContext中初始化userId与setUserId(初始值为null),登录时将用户ID存入userId,但登录后点击个人页,URL显示为/users/null,无法正常跳转。
UserContext代码
import React, { createContext, useState } from 'react'; export const UserContext = createContext({}); export function UserContextProvider({ children }) { const [userInfo, setUserInfo] = useState({}); const [userId, setUserId] = useState(null); return ( <UserContext.Provider value={{ userId, setUserId }}> {children} </UserContext.Provider> ); }
登录页面代码
import React, { useContext, useState } from "react"; import { Navigate } from "react-router-dom"; import "../../styles/LoginPage.css"; import { Link } from "react-router-dom"; import axios from "axios"; import { UserContext } from "../UserContext"; function LoginPage({ isLoggedIn,setIsLoggedIn }) { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [redirect, setRedirect] = useState(false); const [errorMessage, setErrorMessage] = useState(""); const { setUserId } = useContext(UserContext); const login = async (ev) => { ev.preventDefault(); try { const response = await axios.post( `http://localhost:8000/users/login`, { email, password, }, { withCredentials: true, } ); console.log(response); if (response.data.errors) { setErrorMessage("Erreur lors de la connexion"); } else { setIsLoggedIn(true); // Mettre à jour l'état global de connexion setRedirect(true); // Définir la redirection setUserId(response.userId); } } catch (error) { console.error("Error:", error); setErrorMessage("Informations incorrectes"); } }; if (redirect) { return <Navigate to="/" />; } return ( <form onSubmit={login}> <h1 className="login-title">Login</h1> <input type="email" placeholder="Email" value={email} onChange={(ev) => setEmail(ev.target.value)} /> <input type="password" placeholder="Mot de passe" value={password} onChange={(ev) => setPassword(ev.target.value)} /> {errorMessage && <p className="error-message">{errorMessage}</p>} <button className="my-button">Connexion</button> <Link to="/register"> <button className="my-button">Pas de compte ?</button> </Link> </form> ); } export default LoginPage;
布局页面代码
import '../styles/Layout.css' import skull from '../assets/bg3.gif' import { Link, useNavigate } from "react-router-dom"; import { Outlet } from "react-router-dom"; import React, { useContext } from 'react'; import { UserContext } from './UserContext'; function Layout({isLoggedIn,setIsLoggedIn}) { const title_header = "True Crime Story"; const navigate = useNavigate(); const { userId } = useContext(UserContext); const handleLogout = async () => { try { // Effectuer les actions de déconnexion, tels que la suppression du cookie, etc. setIsLoggedIn(false); navigate("/login"); // Effectuer la redirection vers la page d'accueil ("/") } catch (error) { console.error("Error during logout:", error); } }; return ( <div> <div className="header"> <div className="main-title"> <h1>{title_header}</h1> </div> <ul className="side-bar"> <li><Link to="/">Accueil</Link></li> {isLoggedIn && ( <> <li> <Link to={`/users/${userId}`}>Profil</Link> </li> <li> <button onClick={handleLogout}>Déconnexion</button> </li> </> )} {!isLoggedIn && ( <li> <Link to="/login">Connexion</Link> </li> )} <li><Link to="/articles">Articles</Link></li> <li><Link to="/infos">Infos</Link></li> </ul> </div> <div className="body"> <div className="modal"> <div className="modal-content"> <Outlet /> </div> </div> </div> <img src={skull} className="image-skull" alt="skull-gif" /> </div> ); } export default Layout;
解决方案
核心问题分析
- 后端数据获取路径错误:登录接口返回的用户ID实际在
response.data对象中,但代码里直接取response.userId,导致setUserId传入undefined,userId始终为null。 - 状态不同步:
isLoggedIn通过props传递,userId通过Context管理,两者更新时机不一致,可能出现isLoggedIn已为true但userId仍未更新的情况,此时点击个人页会拼接出/users/null。
具体修复步骤
1. 修正登录接口的用户ID获取
在LoginPage的login函数中,将setUserId(response.userId)修改为setUserId(response.data.userId):
// 原代码 setUserId(response.userId); // 修改后 setUserId(response.data.userId);
2. 统一用户状态到Context(推荐)
将isLoggedIn和setIsLoggedIn移入UserContext,避免跨组件状态不一致:
// 修改后的UserContext import React, { createContext, useState } from 'react'; export const UserContext = createContext({}); export function UserContextProvider({ children }) { const [userInfo, setUserInfo] = useState({}); const [userId, setUserId] = useState(null); const [isLoggedIn, setIsLoggedIn] = useState(false); // 新增状态 return ( <UserContext.Provider value={{ userId, setUserId, isLoggedIn, setIsLoggedIn }}> {children} </UserContext.Provider> ); }
然后更新LoginPage,不再通过props接收isLoggedIn和setIsLoggedIn:
// 修改后的LoginPage组件定义 function LoginPage() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [redirect, setRedirect] = useState(false); const [errorMessage, setErrorMessage] = useState(""); const { setUserId, setIsLoggedIn } = useContext(UserContext); // 从Context获取 // ... 其余代码不变 }
同样更新Layout组件:
// 修改后的Layout组件定义 function Layout() { const title_header = "True Crime Story"; const navigate = useNavigate(); const { userId, isLoggedIn, setIsLoggedIn } = useContext(UserContext); // 从Context获取 // ... 其余代码不变 }
3. 增加个人页链接的安全判断
在Layout中,确保userId存在时才渲染个人页链接,避免无效跳转:
{isLoggedIn && userId && ( <> <li> <Link to={`/users/${userId}`}>Profil</Link> </li> <li> <button onClick={handleLogout}>Déconnexion</button> </li> </> )}
内容的提问来源于stack exchange,提问作者yunaie
相关产品推荐
相关产品推荐

