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

React useAuth钩子返回null致私有路由无法访问问题排查

问题描述

我创建了useAuth钩子用于授权用户访问私有路由,授权Cookie已正确存储,但useAuth钩子却返回null。尝试打印setUser的值时,setUser(res.data.currentUser)后的日志未输出,而此前的日志能正常打印出正确的Cookie信息。手动访问私有路由时,useAuth返回的setUser为null,导致无法访问该路由。本项目采用React作为前端框架,Node.js+Express作为后端,我已尝试通过日志排查、使用useEffect调用相关函数,但仍未解决问题。


相关代码

useAuth钩子代码

import { useState, useContext, useEffect } from "react";
import { UserContext } from "./UserContext";
import axios from "axios";

export default function useAuth() {
  const { setUser } = useContext(UserContext);
  const [error, setError] = useState(null);

  useEffect(() => {
    console.log("USE effect");
    setUserContext();
  });

  //set user in context and push them home
  const setUserContext = async () => {
    console.log("In here");
    return await axios
      .get("auth/checkAuth")
      .then((res) => {
        console.log("RES>DATA = ", res.data.currentUser); // PRINTS THE CORRECT COOKIE VALUES
        setUser(res.data.currentUser); // THIS SEEMS TO BE NULL?????
        console.log("SET USER + ", setUser);  // THIS DOES NOT PRINT
      })
      .catch((err) => {
        setError(err);
      });
  };

  return {
    setUser,
  };
}

私有路由代码

import React, { useContext } from 'react';
import {Route, Redirect, Navigate} from 'react-router-dom';
import { UserContext } from '../hooks/UserContext';
import useAuth from '../hooks/useAuth';


export default function PrivateRoute({children}) {
   const auth = useAuth();
   console.log("aUTH in priv = ", auth);
   return auth ? children : <Navigate to="/"/>
}

App.js代码

import "./App.css";
import { Redirect, Route, Routes, Switch } from "react-router-dom";
import useFetch from "./useFetch";
import { useEffect, useState, useRef } from "react";
import axios from "axios";
import Activities from "./components/Activities";
import HomePage from "./components/Home";
import Map from "./components/Map";

import checkUser from "./hooks/checkUser";

import { UserContext } from "./hooks/UserContext";
import useFindUser from "./hooks/checkUser";
import PrivateRoute from "./components/PrivateRoute";

function App() {
  const [auth, setAuth] = useState(false);
  const [activities, setActivities] = useState([]);
  const notInitialRender = useRef(false);
  const { user, setUser, isLoading } = useFindUser(); // works as expected


  
  return (
    <div className="App">
      <UserContext.Provider value={{ user, setUser, isLoading }}>
        <Routes>
          <Route path="/" element={<HomePage />}></Route>
          <Route path="/Activities" element={<Activities />} />
          <Route
            path="/Private"
            element={
              <PrivateRoute>
                <Map />
              </PrivateRoute>
            }
          />
        </Routes>
      </UserContext.Provider>
    </div>
  );
}

export default App;

Express的auth/checkAuth路由代码

export const checkAuth = (req, res) => {

  let currentUser;
  console.log("res.cookies = ", req);
  if (req.cookies.currentUser) {
    // res.send(200);
    currentUser = req.cookies.currentUser; // set to user object in cookies
    console.log("current user = ", currentUser);
    // return 200 status code
  } else {
    currentUser = null;
  }
  //res.json(currentUser);
  res.status(200).send({ currentUser });
};

Map私有组件代码

import react from 'react';



function Map() {
    <div>
        <p style={{color:'red'}}>You have access to the private route</p>
    </div>
}

export default Map;

UserContext代码

import { createContext } from "react";

export const UserContext = createContext("null");

问题分析与修复方案

核心问题点

  1. useAuth返回值逻辑错误:当前返回的是{setUser}函数对象,而非用户授权状态(是否存在有效用户),导致私有路由判断依据错误。
  2. setUser调用后日志未执行:大概率是setUser为undefined,调用时抛出错误,但catch块未打印错误信息,无法定位问题。
  3. useEffect无依赖数组:导致组件每次渲染都重复调用setUserContext,引发无限循环。
  4. 私有路由判断逻辑错误:用setUser对象存在性作为授权依据,而非用户是否存在。
  5. Map组件语法错误:缺少return语句,无法渲染内容。

修复步骤

1. 重构useAuth钩子,返回正确的授权状态

import { useState, useContext, useEffect } from "react";
import { UserContext } from "./UserContext";
import axios from "axios";

export default function useAuth() {
  const { user, setUser } = useContext(UserContext);
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  // 仅组件挂载时执行一次授权检查
  useEffect(() => {
    const fetchAuthStatus = async () => {
      try {
        // 跨域场景需添加withCredentials: true确保Cookie被携带
        const res = await axios.get("auth/checkAuth", { withCredentials: true });
        console.log("RES>DATA = ", res.data.currentUser);
        
        if (res.data.currentUser) {
          setUser(res.data.currentUser);
        }
        console.log("SET USER 执行完成");
      } catch (err) {
        setError(err);
        console.error("授权检查错误:", err); // 打印错误便于定位
      } finally {
        setIsLoading(false);
      }
    };

    fetchAuthStatus();
  }, []);

  // 返回用户授权状态、加载状态、错误信息
  return {
    isAuthenticated: !!user, // 转换为布尔值,存在用户则为true
    isLoading,
    error
  };
}

2. 修正私有路由的判断逻辑

import React from 'react';
import { Navigate } from 'react-router-dom';
import useAuth from '../hooks/useAuth';

export default function PrivateRoute({ children }) {
  const { isAuthenticated, isLoading } = useAuth();

  // 加载中显示占位组件,避免跳转闪烁
  if (isLoading) {
    return <div>加载中...</div>;
  }

  // 根据用户是否存在判断是否允许访问
  return isAuthenticated ? children : <Navigate to="/" />;
}

3. 修正UserContext默认值

import { createContext } from "react";

// 设置更合理的默认值结构,避免混淆
export const UserContext = createContext({
  user: null,
  setUser: () => {},
  isLoading: false
});

4. 修复Map组件语法错误

import React from 'react';

function Map() {
  return (
    <div>
      <p style={{color:'red'}}>You have access to the private route</p>
    </div>
  );
}

export default Map;

内容的提问来源于stack exchange,提问作者program.exe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:30:40