reactjsreact-hooksaxios

I am Wondering if this useEffect Actually Only Runs When the useMemo has Nothing in it


So, I am wondering if this makes sense at all. I am trying to cache the data/users when the data is fetched with Axios, but make this useEffect run only when cachedUsers.length has no length. Does this have any propose or is there a better way to do this?

import { useState, useEffect, useMemo } from "react";
import { useNavigate } from "react-router-dom";
import axios from "axios";

const GetAllUsers = () => {
  const [fsUsers, setFsUsers] = useState([]);
  const [notFoundErr, setNotFoundErr] = useState("");
  const [loading, toggleLoading] = useState(true);
  const navigate = useNavigate();

  const cachedUsers = useMemo(() => fsUsers, [fsUsers]);

  // Gets all users in Firestore DB.
  useEffect(() => {
    const fetchUsers = async () => {
      try {
        toggleLoading(true);
        const res = await axios({
          method: "GET",
          url: "http://localhost:4000/auth/api/firebase/users",
          validateStatus: (status) => {
            return status === 200 || status === 404;
          },
        });
        console.log(res.data);
        if (res && res.status === 200) {
          setFsUsers(res.data);
        } else if (res && res.status === 404) {
          setNotFoundErr("No users found.");
        }
      } catch (error) {
        console.error(error);
        navigate("/error500");
      } finally {
        toggleLoading(false);
      }
    };
    fetchUsers();
  }, [!cachedUsers.length]);

  return [cachedUsers, notFoundErr, loading];
};

export default GetAllUsers;

Solution

  • This is what I was trying to aim for. Cache the user (for profile page) when the user visits that page for the first time. Then when the user navigates to that page again, it doesn't have to send that request to the server and not waste time and resources.

    // CacheContext.js
    import { createContext, useState, useEffect } from "react";
    
    export const CacheContext = createContext();
    
    export const CacheProvider = ({ children }) => {
      const [cache, setCache] = useState({ userProfile: null });
    
      return (
        <CacheContext.Provider value={{ cache, setCache }}>
          {children}
        </CacheContext.Provider>
      );
    };
    
    // useCache.js
    import { useContext } from "react";
    import { CacheContext } from "../contexts/cache";
    
    const useCache = () => {
      return useContext(CacheContext);
    };
    
    export default useCache;
    
    // GetUser.js
    import { useState, useEffect } from "react";
    import { useNavigate } from "react-router-dom";
    import axios from "axios";
    
    import useCache from "../../../hooks/useCache";
    
    const GetUser = (id) => {
      const [notFoundErr, setNotFoundErr] = useState("");
      const { cache, setCache } = useCache();
      const navigate = useNavigate();
    
      // Gets stored user.
      useEffect(() => {
        let abortController;
    
        const fetchDetails = async () => {
          try {
            if (cache.userProfile === null) {
              abortController = new AbortController();
              setNotFoundErr("");
              const res = await axios({
                method: "GET",
                url: `http://localhost:4000/auth/api/firebase/users/${id}`,
                signal: abortController.signal,
                validateStatus: (status) => {
                  return status === 200 || status === 404;
                },
              });
              // console.log(res.data);
    
              if (res && res.status === 200) {
                setCache((prev) => ({ ...prev, userProfile: res.data }));
              } else if (res && res.status === 404) {
                setNotFoundErr(res.data.user);
              }
            }
          } catch (error) {
            if (error.code === "ECONNABORTED" || error.message === "canceled") {
              console.warn("Request was aborted.");
            } else {
              console.error(error);
              navigate("/error500");
            }
          }
        };
        fetchDetails();
    
        return () => {
          if (abortController) abortController.abort();
        };
      }, []);
    
      return [cache.userProfile, notFoundErr];
    };
    
    export default GetUser;