98 lines
3.1 KiB
JavaScript
98 lines
3.1 KiB
JavaScript
// 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';
|
||
|
||
/**
|
||
* 认证弹窗自定义 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 }));
|
||
}, [dispatch]);
|
||
|
||
/**
|
||
* 关闭认证弹窗
|
||
* 如果用户未登录且不在首页,跳转到首页
|
||
*/
|
||
const closeAuthModal = useCallback(() => {
|
||
dispatch(closeModal());
|
||
onSuccessCallbackRef.current = null;
|
||
|
||
// ⭐ 如果用户关闭弹窗时仍未登录,且当前不在首页,才跳转到首页
|
||
if (!isAuthenticated && window.location.pathname !== '/home') {
|
||
navigate('/home');
|
||
}
|
||
}, [dispatch, isAuthenticated, navigate]);
|
||
|
||
/**
|
||
* 登录/注册成功处理
|
||
* @param {object} user - 用户信息
|
||
*/
|
||
const handleLoginSuccess = useCallback((user) => {
|
||
// 执行自定义回调(如果有)
|
||
if (onSuccessCallbackRef.current) {
|
||
try {
|
||
onSuccessCallbackRef.current(user);
|
||
} catch (error) {
|
||
console.error('useAuthModal: handleLoginSuccess 回调执行失败', error);
|
||
}
|
||
}
|
||
|
||
// ⭐ 登录成功后,只关闭弹窗,留在当前页面(不跳转)
|
||
// 移除了原有的 redirectUrl 跳转逻辑
|
||
dispatch(closeModal());
|
||
onSuccessCallbackRef.current = null;
|
||
}, [dispatch]);
|
||
|
||
return {
|
||
// 状态
|
||
isAuthModalOpen,
|
||
redirectUrl,
|
||
|
||
// 方法
|
||
openAuthModal,
|
||
closeModal: closeAuthModal,
|
||
handleLoginSuccess,
|
||
};
|
||
};
|