En mis días de principiante creando aplicaciones web completas con ReactJs, me encontré confundido acerca de cómo manejar la autenticación en la interfaz. Quiero decir, ¿qué deberías hacer a continuación después de recibir tu token de acceso del backend? ¿Cómo se conserva el estado de inicio de sesión?
La mayoría de los principiantes asumirían "Oh, simplemente guarda tu token en el estado". Pero descubrí rápidamente que no era la mejor solución, ni siquiera es una solución porque, como saben los desarrolladores más experimentados de ReactJs, el estado es temporal porque se borra cada vez que actualizas la página y definitivamente podemos hacerlo. No es posible que el usuario inicie sesión cada vez que actualiza.
Avanzando ahora que he adquirido un poco de experiencia en la creación de aplicaciones de pila completa en React, estudiando el enfoque de autenticación de un desarrollador más experimentado y replicando el proceso en otras dos aplicaciones, me gustaría ofrecer una guía. sobre cómo lo manejo actualmente. Puede que algunas personas no piensen que es la mejor manera, pero yo la he adoptado como mi método por ahora y estoy abierto a aprender otros métodos utilizados por otros desarrolladores.
Enviaste tu correo electrónico y contraseña (asumiendo que estás usando autenticación básica de correo electrónico y contraseña) al backend para iniciar el proceso de autenticación. No hablaré sobre cómo se maneja la autenticación en el backend porque este artículo trata sobre cómo manejar la autenticación únicamente en el frontend. Pasaré a la parte en la que recibió un token en la respuesta HTTP. A continuación se muestra un ejemplo de código de un componente de formulario de inicio de sesión simple que envía el correo electrónico y la contraseña al servidor y recibe el token y la información del usuario en la respuesta. Ahora, en aras de la simplicidad, los valores de mi formulario se administran con el estado; sería mucho mejor usar una biblioteca sólida como formik para aplicaciones de producción.
import axios from 'axios' import { useState } from "react" export default function LoginForm() { const [email, setEmail] = useState("") const [password, setPassword] = useState("") const handleSubmit = async() => { try { const response = await axios.post("/api/auth/login", { email, password }) if (response?.status !== 200) { throw new Error("Failed login") } const token = response?.data?.token const userInfo = response?.data?.userInfo } catch (error) { throw error } } return() }
Envuelva toda su aplicación, o solo las partes que necesitan acceso al estado de autenticación, en un proveedor de contexto de autenticación. Esto se hace comúnmente en su archivo raíz App.jsx. Si no tiene idea de qué es la API de contexto, no dude en consultar los documentos de Reactjs. Los ejemplos siguientes muestran un componente de proveedor AuthContext creado. Luego se importa en App.jsx y se usa para empaquetar el RouterProvider devuelto en el componente de la aplicación, haciendo así que se pueda acceder al estado de autenticación desde cualquier lugar de la aplicación.
import { createContext } from "react"; export const AuthContext = createContext(null) export default function AuthProvider({children}) { return({children} ) }
import React from "react"; import { createBrowserRouter, RouterProvider } from "react-router-dom"; import AuthProvider from "./AuthContext"; const router = createBrowserRouter([ // your routes here ]) function App() { return() } export default App
En el contexto de autenticación, debe inicializar dos variables de estado, "isLoggedIn" y "authenticadeUser". El primer estado es un tipo booleano que inicialmente se establecerá en "falso" y luego se actualizará a "verdadero" una vez que se confirme el inicio de sesión. La segunda variable de estado se utiliza para almacenar la información del usuario que ha iniciado sesión, como nombres, correo electrónico, etc. Estas variables de estado deben incluirse en el valor del proveedor devuelto en el componente de contexto para que puedan ser accesibles en toda la aplicación para la representación condicional. .
import { createContext, useState } from "react"; export const AuthContext = createContext(null) export default function AuthProvider({children}) { const [isLoggedIn, setIsLoggedIn] = useState(false) const [authenticatedUser, setAuthenticatedUser] = useState(null) const values = { isLoggedIn, authenticatedUser, setAuthenticatedUser } return({children} ) }
Nanostores es un paquete para administrar el estado en aplicaciones Javascript. El paquete proporciona una API simple para administrar valores de estado en múltiples componentes simplemente inicializándolo en un archivo separado e importándolo en cualquier componente donde desee utilizar el estado o actualizarlo. Pero, con el fin de almacenar su token de autenticación recibido en la respuesta HTTP en el paso uno, utilizará nanostores/persistent. Este paquete conserva su estado almacenándolo en localStorage, de esa manera no se borra cuando actualiza la página. @nanostores/react es una integración específica de reacción para nanostores, pone a disposición el gancho useStore para extraer valores de un estado de nanostore.
Así que ahora puedes seguir adelante y:
Instala los siguientes paquetes: nanostores, @nanostores/persistent y @nanostores/react.
En un archivo separado llamado user.atom.js o como elijas llamarlo, inicializa una tienda 'authToken' y una tienda 'user' usando nanostores/persistent.
Impórtelos al archivo componente de su formulario de inicio de sesión y actualice el estado con el token y los datos de usuario recibidos en su respuesta de inicio de sesión.
npm i nanostores @nanostores/persistent @nanostores/react
import { persistentMap } from '@nanostores/persistent' export const authToken = persistentMap('token', null) export const user = persistentMap('user', null)
import { authToken, user } from './user.atom' const handleSubmit = async() => { try { const response = await axios.post("/api/auth/login", { email, password }) if (response?.status !== 200) { throw new Error("Failed login") } const token = response?.data?.token const userInfo = response?.data?.userInfo authToken.set(token) user.set(userInfo) } catch (error) { throw error } }
Ahora, en el contexto de autenticación que envuelve su aplicación, debe asegurarse de que el token y los estados del usuario se mantengan actualizados y estén disponibles en toda su aplicación. Para lograr esto, tienes que:
Importa las tiendas 'authToken' y 'user'.
Inicialice un gancho useEffect, dentro del gancho, cree una función 'checkLogin()' que verificará si el token está presente en la tienda 'authToken'; si lo está, ejecute una función para verificar si está venció. Según los resultados de la verificación, puede redirigir al usuario a la página de inicio de sesión para autenticarse O... establecer el estado "isLoggedIn" en verdadero. Ahora, para asegurarse de que se realice un seguimiento del estado de inicio de sesión con más frecuencia, este enlace se puede configurar para que se ejecute cada vez que cambie la ruta actual, de esta manera, un usuario puede ser expulsado o redirigido a la página de inicio de sesión si su token caduca mientras interactúa con la aplicación. .
Inicializa otro gancho useEffect que contendrá una función para obtener la información del usuario desde el backend usando el token en la tienda authToken cada vez que se carga o actualiza la aplicación. Si recibe una respuesta exitosa, establezca el estado "isLoggedIn" en verdadero y actualice el estado "authenticadeUser" y el almacén de "usuario" con la información del usuario recibida en la respuesta.
A continuación se muestra el archivo del componente AuthProvider actualizado.
import { createContext, useState } from "react"; import { authToken, user } from './user.atom'; import { useStore } from "@nanostores/react"; import { useNavigate, useLocation } from "react-router-dom"; import axios from "axios"; export const AuthContext = createContext(null) export default function AuthProvider({children}) { const [isLoggedIn, setIsLoggedIn] = useState(false) const [authenticatedUser, setAuthenticatedUser] = useState(null) const token = useStore(authToken) const navigate = useNavigate() const { pathname } = useLocation() function isTokenExpired() { // verify token expiration and return true or false } // Hook to check if user is logged in useEffect(() => { async function checkLogin () { if (token) { const expiredToken = isTokenExpired(token); if (expiredToken) { // clear out expired token and user from store and navigate to login page authToken.set(null) user.set(null) setIsLoggedIn(false); navigate("/login"); return; } } }; checkLogin() }, [pathname]) // Hook to fetch current user info and update state useEffect(() => { async function fetchUser() { const response = await axios.get("/api/auth/user", { headers: { 'Authorization': `Bearer ${token}` } }) if(response?.status !== 200) { throw new Error("Failed to fetch user data") } setAuthenticatedUser(response?.data) setIsLoggedIn(true) } fetchUser() }, []) const values = { isLoggedIn, authenticatedUser, setAuthenticatedUser } return({children} ) }
Ahora, estos dos enlaces useEffect creados en el paso cinco son responsables de mantener administrado todo el estado de autenticación de su aplicación. Cada vez que realiza una actualización, se ejecutan para verificar su token en el almacenamiento local, recuperar los datos de usuario más recientes directamente desde el backend y actualizar su estado "isLoggedIn" y "authentiatedUser". Puede usar los estados dentro de cualquier componente importando el enlace 'AuthContext' y 'useContext' de reaccionar y llamándolos dentro de su componente para acceder a los valores y usarlos para alguna representación condicional.
import { useContext } from "react"; import { AuthContext } from "./AuthContext"; export default function MyLoggedInComponent() { const { isLoggedIn, authenticatedUser } = useContext(AuthContext) return( { isLoggedIn ?Welcome {authenticatedUser?.name}
: } > ) }
Recuerde que al cerrar sesión, debe borrar la tienda 'authToken' y 'user' configurándolas como nulas. También debe establecer "isLoggedIn" en falso y "authenticadeUser" en nulo.
¡Gracias por leer!
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3