Tengo una función useEffect en el componente Layout que obtiene mis datos de userData y los almacena en redux-store , pero se activa con cada cambio de ruta .
Quiero que la función useFffect se ejecute la primera vez y no se vuelva a activar cuando cambie mis rutas. Esto no está bien con el envío de más solicitudes inútiles al servidor. ¿Cómo puedo hacer eso?
Este es mi componente de Layout :
import { useEffect, useState } from "react"; import Navbar from "../navbar/navbar"; import Footer from "../footer/footer"; import Head from "next/head"; import { useCookies } from "react-cookie"; import { useDispatch, useSelector } from "react-redux"; import axios from "axios"; import { getUserData } from "../../redux/actions/Auth"; const Layout = ({ children }) => { const [cookie, setCookie] = useCookies(["token"]); const dispatch = useDispatch(); useEffect(() => { // this useEffect triggers every time i route !! const { token } = cookie; if (token) { axios.defaults.headers.common["Authorization"] = `Bearer ${token}`; dispatch({ type: "IS_LOGGED_IN" }); dispatch(getUserData(token)); } }, []); return ( <div className="layout" dir="rtl"> <Head> <meta name="description" content="" /> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="true" /> <link href="https://fonts.googleapis.com/css2?family=Noto+Kufi+Arabic:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet" /> <link rel="stylesheet" type="text/css" charset="UTF-8" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css" /> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css" /> </Head> <Navbar /> {children} <Footer /> </div> ); }; export default Layout; Está utilizando el gancho useEffect que se activó en el componente montado, también se activará con cada cambio de ruta que es el comportamiento predeterminado y correcto del gancho useEffect ya que lo usa en el componente Layout y se volverá a procesar con cada cambio de ruta.
Existen algunas soluciones para manejar estos casos, como implementar getUserData(token) en un componente principal del componente Layer que no se vuelve a procesar en cada cambio de ruta.
Otra solución es usar otra variable de estado para mantener el estado de la llamada a la API. tiene una acción IS_LOGGED_IN que puede cambiar su reductor de esta manera:
case IS_LOGGED_IN: return { ...state, isUserLoggedIn: true } Por lo tanto, debe obtener y verificar esta propiedad de muestra en useEffect antes de enviar getUserData :
const isLoggedIn = useSelector(state => state.user.isUserLoggedIn) // get isUserLoggedIn from the state useEffect(() => { if (!isLoggedIn) { // -----> getUserData if user is not logged in const {token} = cookie; if (token) { axios.defaults.headers.common["Authorization"] = `Bearer ${token}`; dispatch({ type: "IS_LOGGED_IN" }); dispatch(getUserData(token)); } } }, [isLoggedIn]); una vez que usa el componente Layout , el valor isLoggedIn es falso (ya que el usuario no ha iniciado sesión), por lo que el método dispatch(getUserData(token)) llamará y obtendrá los datos. después de eso, isLoggedIn cambiará a true para que la declaración condicional en useEffect lo verifique y no permita enviar getUserData nuevamente.
Nota: Es posible que necesite otra acción con el procedimiento adecuado en el reducer para alternar entre que el usuario haya iniciado sesión o no haya iniciado sesión en la aplicación.