## 主要改动 ### 新增 - 创建 `store/slices/authModalSlice.js` - Redux Slice 管理认证弹窗状态 - 创建 `hooks/useAuthModal.js` - 自定义 Hook,组合 Redux 状态和业务逻辑 ### 修改 - 更新 `store/index.js` - 添加 authModal reducer - 更新 `App.js` - 移除 AuthModalProvider 包裹层 - 更新 5 个组件的 import 路径: - AuthFormContent.js - AuthModalManager.js - WechatRegister.js - HomeNavbar.js - ProtectedRoute.js ### 删除 - 删除 `contexts/AuthModalContext.js` - 旧的 Context 实现 ## 迁移效果 - ✅ 减少 Provider 嵌套层级(4层 → 3层) - ✅ 统一状态管理架构(Redux) - ✅ 更好的调试体验(Redux DevTools) - ✅ 保持 API 兼容性(无破坏性修改) ## 技术细节 - 使用 `useRef` 存储 `onSuccessCallback`(函数不可序列化) - 保持与 AuthContext 的依赖关系(AuthProvider 暂未迁移) - 所有业务逻辑保持不变,仅改变状态管理方式 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
52 lines
1.8 KiB
JavaScript
Executable File
52 lines
1.8 KiB
JavaScript
Executable File
// src/components/ProtectedRoute.js - 弹窗拦截版本
|
||
import React, { useEffect, useRef } from 'react';
|
||
import { Box, VStack, Spinner, Text } from '@chakra-ui/react';
|
||
import { useAuth } from '../contexts/AuthContext';
|
||
import { useAuthModal } from '../hooks/useAuthModal';
|
||
|
||
const ProtectedRoute = ({ children }) => {
|
||
const { isAuthenticated, isLoading, user } = useAuth();
|
||
const { openAuthModal, isAuthModalOpen } = useAuthModal();
|
||
|
||
// ⚡ 使用 useRef 保存当前路径,避免每次渲染创建新字符串导致 useEffect 无限循环
|
||
const currentPathRef = useRef(window.location.pathname + window.location.search);
|
||
|
||
// 未登录时自动弹出认证窗口
|
||
useEffect(() => {
|
||
if (!isLoading && !isAuthenticated && !user && !isAuthModalOpen) {
|
||
openAuthModal(currentPathRef.current);
|
||
}
|
||
// ⚠️ 移除 user 依赖,因为 user 对象每次从 API 返回都是新引用,会导致无限循环
|
||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||
}, [isAuthenticated, isLoading, isAuthModalOpen, openAuthModal]);
|
||
|
||
// 显示加载状态
|
||
if (isLoading) {
|
||
return (
|
||
<Box
|
||
height="100vh"
|
||
display="flex"
|
||
alignItems="center"
|
||
justifyContent="center"
|
||
bg="gray.50"
|
||
>
|
||
<VStack spacing={4}>
|
||
<Spinner size="xl" color="blue.500" thickness="4px" />
|
||
<Text fontSize="lg" color="gray.600">正在验证登录状态...</Text>
|
||
</VStack>
|
||
</Box>
|
||
);
|
||
}
|
||
|
||
// 未登录时,渲染子组件 + 自动打开弹窗(通过 useEffect)
|
||
// 弹窗会在 useEffect 中自动触发,页面正常显示
|
||
if (!isAuthenticated || !user) {
|
||
return children;
|
||
}
|
||
|
||
// 已登录,渲染子组件
|
||
return children;
|
||
};
|
||
|
||
export default ProtectedRoute;
|