50 lines
1.4 KiB
TypeScript
50 lines
1.4 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* Auth → User 同步器
|
|
*
|
|
* AuthStatusChecker 只负责恢复 loginStatus;用户资料由 user machine
|
|
* 管理。这里持续监听登录态变化:
|
|
* - notLoggedIn → 清空本地 user context
|
|
* - guest / email / OAuth → 重新 hydrate user store
|
|
*/
|
|
import { useEffect, useRef } from "react";
|
|
import { shallowEqual } from "@xstate/react";
|
|
|
|
import type { LoginStatus } from "@/data/schemas/auth";
|
|
import {
|
|
selectAuthIsLoading,
|
|
useAuthSelector,
|
|
} from "@/stores/auth/auth-context";
|
|
import { useUserDispatch } from "@/stores/user/user-context";
|
|
|
|
export function UserAuthSync() {
|
|
const { hasInitialized, isLoading, loginStatus } = useAuthSelector(
|
|
(state) => ({
|
|
hasInitialized: state.context.hasInitialized,
|
|
isLoading: selectAuthIsLoading(state),
|
|
loginStatus: state.context.loginStatus,
|
|
}),
|
|
shallowEqual,
|
|
);
|
|
const userDispatch = useUserDispatch();
|
|
const prevLoginStatusRef = useRef<LoginStatus | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!hasInitialized || isLoading) return;
|
|
|
|
const prev = prevLoginStatusRef.current;
|
|
if (prev === loginStatus) return;
|
|
prevLoginStatusRef.current = loginStatus;
|
|
|
|
if (loginStatus === "notLoggedIn") {
|
|
userDispatch({ type: "UserClearLocal" });
|
|
return;
|
|
}
|
|
|
|
userDispatch({ type: "UserInit" });
|
|
}, [hasInitialized, isLoading, loginStatus, userDispatch]);
|
|
|
|
return null;
|
|
}
|