Maison > interface Web > js tutoriel > 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

王林
Libérer: 2024-09-08 22:34:33
original
975 Les gens l'ont consulté

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>;
};
Copier après la connexion

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;
};
Copier après la connexion

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>
  );
};
Copier après la connexion

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;
  }
};
Copier après la connexion

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";
  }
};
Copier après la connexion

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 });
  }
};
Copier après la connexion

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]);
Copier après la connexion

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];
}
Copier après la connexion

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!

source:dev.to
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal