React Hooksの標準APIであるuseReducerとuseContextを用いて、Reduxライクなグローバルstate管理をTypeScriptで記述しましたので、共有します。
ユーザの認証状況(status)・認証トークン(token)の2つのstateをグローバル管理し、useAuthState・useAuthDispatchでstateとdispatchを提供します。
import文は省略致します。
Types.context.tsx
import React from "react";
export type UnauthenticatedType = "Unauthenticated";
export type AuthenticatedType = "Authenticated";
export type AuthStatus =
| UnauthenticatedType
| AuthenticatedType;
export type Token = string | null;
export type AuthActionType =
| { type: "COMPLETE_SIGNUP"; token: Token }
| { type: "SET_TOKEN"; token: Token };
export type AuthState = {
status: AuthStatus;
token: Token;
};
export type AuthDispatch = React.Dispatch<AuthActionType>;
AuthContext.tsx
const authReducer = (prevState: AuthState, action: AuthActionType) => {
let _status = prevState.status;
switch (action.type) {
case "COMPLETE_SIGNUP":
if (prevState.token) return { ...prevState };
return {
...prevState,
status: AUTHENTICATED,
token: action.token,
};
case "SET_TOKEN":
if (prevState.token) return { ...prevState };
return {
...prevState,
token: action.token,
};
default:
console.warn(`Not found this action.type`);
return { ...prevState };
}
};
export const UNAUTHENTICATED: UnauthenticatedType = "Unauthenticated"; // signup処理前.
export const AUTHENTICATED: AuthenticatedType = "Authenticated"; // signup処理後.
const AuthStateContext = createContext<AuthState>({
status: UNAUTHENTICATED,
token: null,
});
const AuthDispatchContext = createContext<AuthDispatch>(() => {
return;
});
export const useAuthState = (): AuthState => {
const context = useContext(AuthStateContext);
return context;
};
export const useAuthDispatch = (): AuthDispatch => {
const context = useContext(AuthDispatchContext);
return context;
};
type Props = {
status: AuthStatusType;
token: string;
};
export const AuthProvider: React.FC<Props> = ({
children,
status,
token,
}) => {
const initAuthState: AuthState = {
status: status ? status : UNAUTHENTICATED,
token: token ? token : null,
};
const [authState, authDispatch] = useReducer(authReducer, initAuthState);
return (
<AuthStateContext.Provider value={authState}>
<AuthDispatchContext.Provider value={authDispatch}>
{children}
</AuthDispatchContext.Provider>
</AuthStateContext.Provider>
);
};
コメント