首页 >web前端 >js教程 >使用 useContext API 管理 React 中的身份验证状态

使用 useContext API 管理 React 中的身份验证状态

王林
王林原创
2024-09-08 22:34:33988浏览

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