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

React+Django+JWT:如何实现服务端登录状态校验?

问题分析与解决方案

你的核心问题是React组件不能直接返回Promise作为JSX,必须同步渲染内容;同时异步函数的写法可以优化,逻辑更清晰。以下是分步解决的方案:

1. 优化isLoggedIn异步函数

去掉async/await和.then()混用的冗余写法,简化逻辑并增加异常处理:

function saveToken(data) {
  localStorage.setItem('access_token', data.access);
  localStorage.setItem('refresh_token', data.refresh);
  return true;
}

async function isLoggedIn() {
  const accessToken = localStorage.getItem('access_token');
  const refreshToken = localStorage.getItem('refresh_token');

  // 本地无token直接判定未登录
  if (!accessToken || !refreshToken) return false;

  try {
    // 先用access token校验
    await axios.post('api/getuser/', {}, {
      headers: { Authorization: `Bearer ${accessToken}` }
    });
    return true;
  } catch (accessErr) {
    // access token失效,尝试刷新
    try {
      const refreshRes = await axios.post('api/token/refresh/', {
        refresh: refreshToken
      });
      saveToken(refreshRes.data);
      return true;
    } catch (refreshErr) {
      // 刷新失败,清除本地无效token
      localStorage.removeItem('access_token');
      localStorage.removeItem('refresh_token');
      return false;
    }
  }
}

2. 重构React组件,用状态管理异步结果

React组件必须同步返回JSX,所以需要用useState存储授权状态,useEffect触发异步校验,同时处理加载状态:

import { useState, useEffect } from 'react';
import { Navigate, useLocation, useOutlet } from 'react-router-dom';

const ComponentMainArea = () => {
  const location = useLocation();
  const element = useOutlet();
  // null表示校验中,true/false表示授权状态
  const [isAuthenticated, setIsAuthenticated] = useState(null);

  useEffect(() => {
    const checkAuth = async () => {
      const authStatus = await isLoggedIn();
      setIsAuthenticated(authStatus);
    };
    checkAuth();
  }, []);

  // 校验中显示加载提示,避免组件渲染异常
  if (isAuthenticated === null) {
    return <div>加载中...</div>;
  }

  // 未授权则跳转登录页,记录当前路径方便登录后返回
  if (!isAuthenticated) {
    return <Navigate to="/proxy/8000/login" state={{ from: location.pathname }} />;
  }

  // 授权通过,渲染页面内容
  return (
    <div className='mainarea'>
      <AnimatePresence mode='wait' initial={true}>
        {element && React.cloneElement(element, { key: location.pathname })}
      </AnimatePresence>
    </div>
  );
};

3. 进阶优化建议

  • 全局状态管理:把授权状态放到React Context或Redux中,避免每个组件重复调用校验接口,提升性能。
  • 路由守卫封装:可以封装一个ProtectedRoute组件,统一处理所有需要授权的路由,减少代码冗余。
  • 请求拦截器:在Axios中添加请求拦截器,自动在请求头携带token,无需每个请求手动设置。

内容的提问来源于stack exchange,提问作者Maxim Quitom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:33:19