feat: 将 AuthModalProvider 迁移到 Redux
## 主要改动 ### 新增 - 创建 `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>
This commit is contained in:
116
src/hooks/useAuthModal.js
Normal file
116
src/hooks/useAuthModal.js
Normal file
@@ -0,0 +1,116 @@
|
||||
// src/hooks/useAuthModal.js
|
||||
// 认证弹窗自定义 Hook - 组合 Redux 状态和业务逻辑
|
||||
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
openModal,
|
||||
closeModal,
|
||||
selectAuthModalOpen,
|
||||
selectRedirectUrl
|
||||
} from '../store/slices/authModalSlice';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { logger } from '../utils/logger';
|
||||
|
||||
/**
|
||||
* 认证弹窗自定义 Hook
|
||||
*
|
||||
* 功能:
|
||||
* - 管理认证弹窗的开关状态
|
||||
* - 处理登录成功后的回调和跳转
|
||||
* - 未登录时关闭弹窗自动跳转到首页
|
||||
*
|
||||
* 注意:
|
||||
* - onSuccessCallback 使用 ref 存储(函数不可序列化,不能放 Redux)
|
||||
* - 依赖 AuthContext 读取 isAuthenticated(AuthProvider 暂未迁移)
|
||||
*
|
||||
* @returns {object} 弹窗状态和操作方法
|
||||
*/
|
||||
export const useAuthModal = () => {
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Redux 状态
|
||||
const isAuthModalOpen = useSelector(selectAuthModalOpen);
|
||||
const redirectUrl = useSelector(selectRedirectUrl);
|
||||
|
||||
// AuthContext 状态(暂未迁移到 Redux)
|
||||
const { isAuthenticated } = useAuth();
|
||||
|
||||
// 使用 ref 存储回调函数(不能放 Redux,因为函数不可序列化)
|
||||
const onSuccessCallbackRef = useRef(null);
|
||||
|
||||
/**
|
||||
* 打开认证弹窗(统一的登录/注册入口)
|
||||
* @param {string} url - 认证成功后的重定向URL(可选)
|
||||
* @param {function} callback - 认证成功后的回调函数(可选)
|
||||
*/
|
||||
const openAuthModal = useCallback((url = null, callback = null) => {
|
||||
onSuccessCallbackRef.current = callback;
|
||||
dispatch(openModal({ redirectUrl: url }));
|
||||
|
||||
logger.debug('useAuthModal', '打开认证弹窗', {
|
||||
redirectUrl: url || '无',
|
||||
hasCallback: !!callback
|
||||
});
|
||||
}, [dispatch]);
|
||||
|
||||
/**
|
||||
* 关闭认证弹窗
|
||||
* 如果用户未登录,跳转到首页
|
||||
*/
|
||||
const closeAuthModal = useCallback(() => {
|
||||
dispatch(closeModal());
|
||||
onSuccessCallbackRef.current = null;
|
||||
|
||||
// ⭐ 如果用户关闭弹窗时仍未登录,跳转到首页
|
||||
if (!isAuthenticated) {
|
||||
navigate('/home');
|
||||
logger.debug('useAuthModal', '未登录关闭弹窗,跳转到首页');
|
||||
} else {
|
||||
logger.debug('useAuthModal', '关闭认证弹窗');
|
||||
}
|
||||
}, [dispatch, isAuthenticated, navigate]);
|
||||
|
||||
/**
|
||||
* 登录/注册成功处理
|
||||
* @param {object} user - 用户信息
|
||||
*/
|
||||
const handleLoginSuccess = useCallback((user) => {
|
||||
// 执行自定义回调(如果有)
|
||||
if (onSuccessCallbackRef.current) {
|
||||
try {
|
||||
onSuccessCallbackRef.current(user);
|
||||
logger.debug('useAuthModal', '执行成功回调', {
|
||||
userId: user?.id
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('useAuthModal', 'handleLoginSuccess 回调执行失败', error, {
|
||||
userId: user?.id,
|
||||
hasCallback: !!onSuccessCallbackRef.current
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ⭐ 登录成功后,只关闭弹窗,留在当前页面(不跳转)
|
||||
// 移除了原有的 redirectUrl 跳转逻辑
|
||||
dispatch(closeModal());
|
||||
onSuccessCallbackRef.current = null;
|
||||
|
||||
logger.debug('useAuthModal', '登录成功,关闭弹窗', {
|
||||
userId: user?.id
|
||||
});
|
||||
}, [dispatch]);
|
||||
|
||||
return {
|
||||
// 状态
|
||||
isAuthModalOpen,
|
||||
redirectUrl,
|
||||
|
||||
// 方法
|
||||
openAuthModal,
|
||||
closeModal: closeAuthModal,
|
||||
handleLoginSuccess,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user