이 코드 조각은 React 애플리케이션에서 인증 상태를 관리하는 데 필요한 모든 것입니다. Context API를 사용하여 애플리케이션 전체에서 사용자 상태를 관리합니다.
더 이상 잡담하지 말고 본격적으로 살펴보겠습니다.
import { createContext, Dispatch, ReactNode, SetStateAction, useContext, useEffect } from "react"; import { useLocalStorage } from "../utils/useLocalStorage"; type SignInForm = { email: string; password: string; }; type User = { id: number; email: string; }; type AuthState = User & { exp: number }; type UserContextType = { user: User | null; setUser: Dispatch<SetStateAction<AuthState | null>>; signOut: () => Promise<string | undefined>; signIn: (signInForm: SignInForm) => Promise<string | undefined>; };
필요한 React 후크와 사용자 정의 useLocalStorage 후크를 가져오는 것부터 시작합니다. 그런 다음 SignInForm, User, AuthState 및 UserContextType을 포함하여 인증 시스템에 대한 TypeScript 유형을 정의합니다.
const AuthDataContext = createContext<UserContextType | undefined>(undefined); export const useAuth = (): UserContextType => { const context = useContext(AuthDataContext); if (!context) { throw new Error("useAuth must be used within a UserDataProvider"); } return context; };
여기에서는 AuthDataContext와 사용자 정의 useAuth 후크를 생성합니다. 이 후크는 공급자 내의 컨텍스트를 사용하고 인증 상태에 액세스하는 편리한 방법을 제공합니다.
export const AuthProvider = ({ children }: { children: ReactNode }) => { const [user, setUser] = useLocalStorage<AuthState | null>("user", null); // ... (other functions) return ( <AuthDataContext.Provider value={{ user, setUser, signIn, signOut }}> {children} </AuthDataContext.Provider> ); };
AuthProvider 구성 요소는 인증 시스템의 핵심입니다. useLocalStorage 후크를 사용하여 사용자 상태를 유지하고 하위 항목에 컨텍스트 값을 제공합니다.
const isJwtExpired = (unixTime: number) => { const currentTime = Math.floor(Date.now() / 1000); const timeRemaining = unixTime - currentTime; if (timeRemaining <= 0) { console.log("The JWT is expired."); setUser(null); return true; } else { const hours = Math.floor(timeRemaining / 3600); const minutes = Math.floor((timeRemaining % 3600) / 60); console.log(`Time remaining before JWT expires: ${hours} hours ${minutes} minutes`); return false; } };
JWT가 만료되었는지 확인하고, 아직 유효한 경우 남은 시간을 기록하는 기능입니다.
const signOut = async () => { const res = await fetch("http://localhost:8080/auth/signout", { method: "POST" }); setUser(null); if (!res.ok) { console.log("Error signing out"); return (await res.text()) || "Something went wrong"; } };
signOut 함수는 로그아웃 엔드포인트에 POST 요청을 보내고 사용자 상태를 지웁니다.
const signIn = async (signInForm: SignInForm) => { const res = await fetch("http://localhost:8080/auth/signin", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(signInForm), }); if (!res.ok) { return (await res.text()) || "Something went wrong"; } const data = (await res.json()) as { user: User; exp: number }; if (data) { setUser({ ...data.user, exp: data.exp }); } };
signIn 함수는 사용자의 자격 증명을 로그인 엔드포인트로 보내고 응답 데이터로 사용자 상태를 업데이트합니다.
useEffect(() => { if (!user) return; if (isJwtExpired(user.exp)) signOut(); }, [user]);
이 효과는 사용자 상태가 변경될 때마다 실행되어 JWT가 만료되었는지 확인하고 필요한 경우 로그아웃합니다.
다음은 useLocalStorage 후크 구현의 예입니다
import { useState, useEffect, Dispatch, SetStateAction } from "react"; export function useLocalStorage<T>( key: string, initialValue: T ): [T, Dispatch<SetStateAction<T>>] { const [storedValue, setStoredValue] = useState<T>(() => { try { const item = localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch (error) { console.log(error); return initialValue; } }); const setValue: Dispatch<SetStateAction<T>> = (value) => { try { const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); localStorage.setItem(key, JSON.stringify(valueToStore)); } catch (error) { console.log(error); } }; useEffect(() => { const handleStorageChange = (event: StorageEvent) => { if (event.key === key) { setStoredValue(JSON.parse(event.newValue || "null")); } }; window.addEventListener("storage", handleStorageChange); return () => window.removeEventListener("storage", handleStorageChange); }, [key]); return [storedValue, setValue]; }
끝났나요? easy peasy 레몬 스퀴지.. 필요한 경우 자신의 API 구조에 대한 가져오기 논리를 수정하세요.
위 내용은 useContext API를 사용하여 반응 시 인증 상태 관리의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!