Maison  >  Article  >  interface Web  >  Gestion de l'état d'authentification en réaction à l'aide de l'API useContext

Gestion de l'état d'authentification en réaction à l'aide de l'API useContext

王林
王林original
2024-09-08 22:34:33955parcourir

Managing Auth State in react using useContext API

Cet extrait de code est tout ce dont vous avez besoin pour gérer l'état d'authentification sur votre application React. Il utilise l'API Context pour gérer l'état des utilisateurs dans l'application.

plus de babillage, plongeons-nous simplement dans le vif du sujet.

Importations et définitions de types

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

Nous commençons par importer les hooks React nécessaires et un hook useLocalStorage personnalisé. Ensuite, nous définissons les types TypeScript pour notre système d'authentification, notamment SignInForm, User, AuthState et UserContextType.

Création du contexte et du hook personnalisé

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

Ici, nous créons le AuthDataContext et un hook useAuth personnalisé. Ce hook garantit que nous utilisons le contexte au sein d'un fournisseur et fournit un moyen pratique d'accéder à notre état d'authentification.

Composant 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>
  );
};

Le composant AuthProvider est le cœur de notre système d'authentification. Il utilise le hook useLocalStorage pour conserver l'état de l'utilisateur et fournit la valeur de contexte à ses enfants.

Vérification de l'expiration 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;
  }
};

Cette fonction vérifie si le JWT a expiré et enregistre le temps restant s'il est toujours valide.

Fonction de déconnexion

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

La fonction signOut envoie une requête POST au point de terminaison de déconnexion et efface l'état de l'utilisateur.

Fonction de connexion

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

La fonction de connexion envoie les informations d'identification de l'utilisateur au point de terminaison de connexion et met à jour l'état de l'utilisateur avec les données de réponse.

useEffect pour le contrôle d'expiration JWT

useEffect(() => {
  if (!user) return;
  if (isJwtExpired(user.exp)) signOut();
}, [user]);

Cet effet s'exécute chaque fois que l'état de l'utilisateur change, vérifiant si le JWT a expiré et se déconnectant si nécessaire.

Voici un exemple d'implémentation du hook useLocalStorage d'ailleurs

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

et tu as fini ? facile à presser au citron. assurez-vous de modifier la logique de récupération pour votre propre structure API si nécessaire.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:.NET Aspire multilingueArticle suivant:.NET Aspire multilingue