
本文介绍在 react 单页应用(spa)首次加载时,通过 useeffect 和 fetch 自动调用后端登录验证接口,并基于返回数据条件渲染模态框的完整实现方案。
本文介绍在 react 单页应用(spa)首次加载时,通过 useeffect 和 fetch 自动调用后端登录验证接口,并基于返回数据条件渲染模态框的完整实现方案。
在构建需要服务端身份校验的前端应用时,一个常见需求是:页面一打开就自动向后端(如 Java Spring Boot 接口)发起登录状态检查,并根据响应结果(例如用户已登录/会话有效/需重新认证)动态展示对应 UI——比如一个带用户信息的欢迎模态框(Modal),或跳转至登录页。
实现这一流程的关键在于触发时机控制与状态驱动渲染。React 中最标准的做法是利用 useEffect 的空依赖数组([])实现组件挂载后的“仅执行一次”的副作用逻辑,并结合 useState 管理异步数据状态。
以下是一个简洁、健壮且生产可用的示例:
import { useState, useEffect } from 'react';
interface LoginResponse {
userId: string;
username: string;
isLoggedIn: boolean;
message?: string;
}
function AuthCheckModal() {
const [data, setData] = useState<LoginResponse | null>(null);
const [loading, setLoading] = useState(true); // 可选:支持加载态反馈
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchAuthStatus = async () => {
try {
setLoading(true);
const res = await fetch('/api/auth/check', {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
// 若需携带凭证(如 cookie 或 token),确保配置 credentials
credentials: 'include', // ✅ 关键:传递 session cookie 给 Java 后端
});
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
}
const result: LoginResponse = await res.json();
setData(result);
} catch (err) {
console.error('Failed to fetch auth status:', err);
setError(err instanceof Error ? err.message : 'Unknown error');
} finally {
setLoading(false);
}
};
fetchAuthStatus();
}, []); // ? 空依赖数组 → 仅在组件挂载后执行一次
// 加载中:可显示骨架屏或 spinner
if (loading) return <div className="loading">Checking login status...</div>;
// 错误处理:避免白屏,提供友好提示
if (error) return <div className="error">Auth check failed: {error}</div>;
// 仅当 data 存在且 isLoggedIn === true 时渲染模态框
return data?.isLoggedIn ? (
<Modal
title="Welcome Back"
onClose={() => setData(null)}
data={data}
/>
) : null; // 或重定向:useNavigate('/login')(需配合 react-router v6+)
}? 关键注意事项:
- ✅ credentials: 'include' 必须显式设置:Java 后端(如 Spring Security)通常依赖 Cookie(如 JSESSIONID)识别会话,若省略此选项,浏览器不会发送 Cookie,导致后端始终判定“未登录”。
- ✅ 避免竞态问题(Race Condition):使用 async/await + try/catch/finally 替代 .then().catch() 链,确保 setLoading(false) 总被执行;同时可在 useEffect 清理函数中添加 abort controller(进阶优化)。
- ✅ 类型安全优先:为 API 响应定义 TypeScript 接口(如 LoginResponse),提升可维护性与开发体验。
- ✅ 服务端配合:确保 Java 接口 /api/auth/check 支持 CORS(允许前端域名)、正确返回 JSON(@ResponseBody / ResponseEntity),并处理未认证请求(如返回 401 而非 500)。
最后,将










