refactor: migrate state imports from contexts to stores directory

This commit is contained in:
2026-06-09 18:47:04 +08:00
parent f79755f6ec
commit a5d8214650
29 changed files with 72 additions and 50 deletions
+87
View File
@@ -0,0 +1,87 @@
"use client";
/**
* AuthContext:基于 XState v5 的 React Context Provider
*
* 业务事件(`Auth*Submitted`)通过 `useMachine(authMachine).send()` 派发。
* XState 自动处理异步副作用(invoke + fromPromise actors)。
*
* 兼容性:保持原 `useAuthState()` / `useAuthDispatch()` API
* 内部将 XState 状态机快照映射回原 `AuthState` 形状。
*/
import {
type Dispatch,
type ReactNode,
createContext,
useContext,
useMemo,
} from "react";
import { useMachine } from "@xstate/react";
import { authMachine } from "./auth-machine";
import type { AuthEvent, AuthContext as MachineContext } from "./auth-machine";
/**
* 对外暴露的 State 形状(保持与原 AuthState 兼容)
*/
export interface AuthState {
authPanelMode: MachineContext["authPanelMode"];
authMode: MachineContext["authMode"];
email: string;
password: string;
username: string;
confirmPassword: string;
isLoading: boolean;
errorMessage: string | null;
isSuccess: boolean;
loginType: MachineContext["loginType"];
}
const AuthStateCtx = createContext<AuthState | null>(null);
const AuthDispatchCtx = createContext<Dispatch<AuthEvent> | null>(null);
export interface AuthProviderProps {
children: ReactNode;
}
export function AuthProvider({ children }: AuthProviderProps) {
const [state, send] = useMachine(authMachine);
// 映射 XState 状态机快照 → 原 AuthState 形状
const authState = useMemo<AuthState>(
() => ({
authPanelMode: state.context.authPanelMode,
authMode: state.context.authMode,
email: state.context.email,
password: state.context.password,
username: state.context.username,
confirmPassword: state.context.confirmPassword,
isLoading: state.matches("loadingEmailLogin") ||
state.matches("loadingEmailRegister") ||
state.matches("loadingFacebookLogin") ||
state.matches("loadingWebGoogleLogin"),
errorMessage: state.context.errorMessage,
isSuccess: state.matches("success"),
loginType: state.context.loginType,
}),
[state],
);
return (
<AuthStateCtx.Provider value={authState}>
<AuthDispatchCtx.Provider value={send}>{children}</AuthDispatchCtx.Provider>
</AuthStateCtx.Provider>
);
}
export function useAuthState(): AuthState {
const ctx = useContext(AuthStateCtx);
if (!ctx) throw new Error("useAuthState must be used inside <AuthProvider>");
return ctx;
}
export function useAuthDispatch(): Dispatch<AuthEvent> {
const ctx = useContext(AuthDispatchCtx);
if (!ctx)
throw new Error("useAuthDispatch must be used inside <AuthProvider>");
return ctx;
}