Files
upage-git/app/.client/hooks/useAuth.ts

80 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useFetcher, useRouteLoaderData } from '@remix-run/react';
/*
* 用户认证Hook
*/
import { useCallback, useEffect, useState } from 'react';
export interface UserInfo {
sub?: string;
name?: string;
// 用户登录名,如果未启用用户名登录则可能为空
username?: string;
picture?: string;
// 用户邮箱,可能为空
email?: string;
// 用户手机号,可能为空
phone_number?: string;
[key: string]: any;
}
interface AuthUserResponse {
isAuthenticated: boolean;
claims?: UserInfo;
}
/**
* useAuth Hook - 获取和管理用户认证状态
*
* 优先使用根加载器数据然后再进行客户端API请求
*/
export function useAuth() {
// 尝试从根加载器获取数据
const rootData = useRouteLoaderData<{ auth?: { isAuthenticated: boolean; userInfo: UserInfo | null } }>('root');
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(rootData?.auth?.isAuthenticated || false);
const [userInfo, setUserInfo] = useState<UserInfo | null>(rootData?.auth?.userInfo || null);
const [isLoading, setIsLoading] = useState<boolean>(!rootData?.auth);
const fetcher = useFetcher<AuthUserResponse>();
useEffect(() => {
if (!rootData?.auth && fetcher.state === 'idle' && !fetcher.data) {
fetcher.load('/api/auth/user');
}
}, [fetcher, rootData]);
// 当获取数据后更新认证状态
useEffect(() => {
if (fetcher.data) {
setIsAuthenticated(fetcher.data.isAuthenticated);
setUserInfo(fetcher.data.isAuthenticated ? fetcher.data.claims || null : null);
setIsLoading(false);
}
}, [fetcher.data]);
// 登录
const signIn = useCallback((callbackUrl = '/api/auth/callback') => {
window.location.href = `/api/auth/sign-in?redirectTo=${encodeURIComponent(callbackUrl)}`;
}, []);
// 登出
const signOut = useCallback(() => {
window.location.href = '/api/auth/sign-out';
}, []);
// 刷新用户信息
const refreshUserInfo = useCallback(() => {
setIsLoading(true);
fetcher.load('/api/auth/user');
}, [fetcher]);
return {
isAuthenticated,
isLoading,
userInfo,
signIn,
signOut,
refreshUserInfo,
};
}