useContext APIを使用したreactでの認証状態の管理

王林
リリース: 2024-09-08 22:34:33
オリジナル
813 人が閲覧しました

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 フックとカスタム 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 フックを作成します。このフックは、プロバイダー内のコンテキストを使用していることを保証し、認証状態にアクセスする便利な方法を提供します。

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 });
  }
};
ログイン後にコピー

サインイン関数は、ユーザーの資格情報をサインイン エンドポイントに送信し、応答データでユーザーの状態を更新します。

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 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!