首頁 >web前端 >js教程 >使用 useContext API 管理 React 中的身份驗證狀態

使用 useContext API 管理 React 中的身份驗證狀態

王林
王林原創
2024-09-08 22:34:33978瀏覽

Managing Auth State in react using useContext API

此程式碼片段是您在 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 hook 和自訂 useLocalStorage hook。然後,我們為我們的驗證系統定義 TypeScript 類型,包括 SignInForm、User、AuthState 和 UserContextType。

建立上下文和自訂掛鉤

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 掛鉤。這個鉤子確保我們使用提供者中的上下文,並提供一種方便的方法來存取我們的身份驗證狀態。

AuthProvider元件

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 掛鉤來保存使用者狀態並為其子級提供上下文值。

JWT 過期檢查

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 函數將使用者的憑證傳送到登入端點,並使用回應資料更新使用者狀態。

JWT 過期檢查的 useEffect

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];
}

你完成了嗎?簡單的檸檬榨汁..如果需要,請確保修改您自己的 api 結​​構的獲取邏輯。

以上是使用 useContext API 管理 React 中的身份驗證狀態的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn