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

React全局Auth状态重定向后变为undefined的问题求助

React全局Auth状态重定向后变为undefined的问题求助

大家好,我正在用React开发一个聊天应用,最近在认证逻辑上碰到了棘手的问题:登录成功后我把accessToken存在了全局的auth状态里,但重定向到聊天页面后,这个auth状态居然变成undefined了!

具体情况是这样的:登录成功后,我通过后端接口能确认已经登录成功,console.log也能看到auth状态更新了:

Updated auth: {accessToken: 'eyJhb......_ucf70'}

可一旦重定向到聊天页面,调用获取聊天记录的接口时就返回401 Unauthorized错误,这明显是auth里的accessToken丢失了——我在useAxiosPrivate.js里打了日志,显示:

this is the auth undefined

下面是我相关的代码片段,麻烦大家帮我排查一下问题所在:

Login.jsx

//... other imports

import axios from '../api/axios';
import useAuth from '../hooks/useAuth';
//...(rest of code)
import { Link, useNavigate, useLocation } from 'react-router-dom';

const LOGIN_URL = '/login';

const Login = () => {
  const { auth, setAuth } = useAuth()
  const navigate = useNavigate()
  const location = useLocation()
  const from = location.state?.from?.pathname || "/chat"

  const [user, setUser] = useState('');
  const [pwd, setPwd] = useState('');
  const [errMsg, setErrMsg] = useState('');

  useEffect(() => {
    userRef.current.focus();
  }, []);

  useEffect(() => {
    setErrMsg('');
  }, [user, pwd]);

  useEffect(() => {
    console.log("Updated auth:", auth);
  }, [auth]);

  useEffect(() => {
    if(auth && auth.accessToken){
      navigate('/chat', { replace: true });
    }
  }, [auth, navigate]);

  const handleSubmit = async (e) => {
    e.preventDefault();

    const formData = new FormData();
    formData.append('username', user);
    formData.append('password', pwd);

    try {
      const response = await axios.post(
        LOGIN_URL,
        formData,
        {
          headers: { 'Content-Type': 'multipart/form-data' },
          withCredentials: true,
        }
      );
      console.log(JSON.stringify(response?.data));
      const accessToken = response?.data.access_token;
      setAuth({accessToken})
      setUser('');
      setPwd('')
      setErrMsg('');
    } catch (err) {
      if (!err?.response) {
        //setErrMsg('No Server Response');    removing for now
        console.log(err);
      } else if (err.response?.status === 400) {
        setErrMsg('Missing Username or Password');
      } else if (err.response?.status === 401) {
        setErrMsg('Unauthorized');
      } else {
        console.log(err);
        setErrMsg('Login Failed');
      }
      errRef.current.focus();
    }
  };

  return (
    // JSX for login
  )
}

export default Login

ChatPage.jsx

//... other imports
import { useState, useEffect, useRef } from "react";
import useRefreshToken from "../hooks/useRefreshToken";
import useAxiosPrivate from "../hooks/useAxiosPrivate";

const ChatPage = () =>  {
  const axiosPrivate = useAxiosPrivate();
  const refresh = useRefreshToken();

  //... unrelated code

  useEffect(() => {
    const fetchChats = async () => {
      try {
        const response = await axiosPrivate.get('/chat/getchats');
        if (response.status === 200) {
          setChats(response.data.map(chat => chat.chat_name));
        } else {
          console.error("Error fetching the chats:", response.data);
        }
      } catch (error) {
        console.error("There was a problem fetching chats:", error);
      }
    };

    fetchChats();
  }, []); // Empty dependency array ensures this useEffect runs only once

  //... rest of ChatPage component
}

axios.js

import axios from "axios"

const BASE_URL ='http://127.0.0.1:8000'

export default axios.create({
  baseURL: BASE_URL
})

export const axiosPrivate = axios.create({
  baseURL: BASE_URL,
  headers: {"Content-Type": "application/json"},
  withCredentials:true
})

AuthProvider.jsx

import { createContext, useState } from "react";

const AuthContext = createContext({});

export const AuthProvider = ({ children }) => {
  const [auth, setAuth] = useState({});

  return (
    <AuthContext.Provider value={{ auth, setAuth }}>
      {children}
    </AuthContext.Provider>
  )
}

export default AuthContext;

useAuth.jsx

import { useContext } from "react";
import AuthContext from "../context/AuthProvider";

const useAuth = () => {
  const { auth } = useContext(AuthContext);
  return useContext(AuthContext);
}

export default useAuth;

useAxiosPrivate.jsx

import { axiosPrivate } from "../api/axios";
import { useEffect } from "react";
import useRefreshToken from "./useRefreshToken";
import useAuth from "./useAuth";

const useAxiosPrivate = () => {
  const refresh = useRefreshToken();
  const { auth } = useAuth();

  useEffect(() => {
    console.log(`this is the auth ${auth.AccessToken}`)
    const requestIntercept = axiosPrivate.interceptors.request.use(
      config => {
        if (!config.headers['Authorization']){
          config.headers['Authorization'] = `Bearer ${auth.AccessToken}`;
        }
        return config;
      }, (error) => Promise.reject(error)
    )

    const responseIntercept = axiosPrivate.interceptors.response.use(
      response => response,
      async (error) => {
        const prevRequest = error?.config;
        if (error?.response?.status ===403 && !prevRequest?.sent) {
          prevRequest.sent = true;
          const newAccessToken = await refresh()
          prevRequest.headers['Authorization'] = `Bearer ${newAccessToken}`;
          return axiosPrivate(prevRequest);
        }
        return Promise.reject(error);
      }
    )

    return () => {
      axiosPrivate.interceptors.request.eject(requestIntercept)
      axiosPrivate.interceptors.response.eject(responseIntercept)
    }
  },[auth, refresh])

  return axiosPrivate;
}

export default useAxiosPrivate;

App.jsx

import {BrowserRouter, Routes, Route} from "react-router-dom"
import HomePage from "./components/HomePage"
import ChatPage from "./components/ChatPage"
import SignUp from "./components/SignUp"
import Login from "./components/Login"
import Layout from "./components/Layout"
import RequireAuth from "./components/RequireAuth"

function App() {
  return (
    <Routes>
      <Route path="/" element={<Layout />}>
        <Route path='/' element = {<HomePage/>} />
        <Route path='/login' element = {<Login/>} />
        <Route path='/signup' element = {<SignUp/>} />
        {/* this is a protected route */}
        <Route element = {<RequireAuth />} >
          <Route path='/chat' element = {<ChatPage/>} />
        </Route>
      </Route>
    </Routes>
  )
}

export default App;

main.jsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Route, Routes } from 'react-router-dom';
import { AuthProvider } from './context/AuthProvider';
import { ThemeProvider } from '@material-tailwind/react';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <ThemeProvider>
      <BrowserRouter>
        <AuthProvider>
          <Routes>
            <Route path="/*" element={<App />} />
          </Routes>
        </AuthProvider>
      </BrowserRouter>
    </ThemeProvider>
  </React.StrictMode>
);

备注:内容来源于stack exchange,提问作者Rodrigo Burberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 11:28:00