skip to Main Content

I am working on a React JS app, where I need to fetch transactions from the backend and display it to the user. Here, I am fetching and displaying transactions with Pagination (50 transactions at once). I have used an useEffect() hook with pageNo in the dependency array so that whenever the page changes new transactions get fetched. Here is my code:

  useEffect(() => {
    setLoading(true);
    axios
      .get(`${TRANSACTIONS_ENDPOINT}`, {
        params: {
          page: paginationConfig.pageNo,
          search_by: searchConfig.search_by,
          search_value: searchConfig.search_value
        },
      })
      .then((response) => {
        const { transactions, total_pages, page} = response.data;
   
        setTransactions(transactions);
        setPaginationConfig({
          ...paginationConfig,
          pageNo: page,
          totalPages: total_pages,
        });
        setLoading(false);
        sessionStorage.setItem(PAGE_STORAGE_KEY, page.toString());
      })
      .catch((err) => {
        console.error(err);
      });
  }, [paginationConfig.pageNo]);

It is working as expected whenever the user navigates to a different page using page navigation at the bottom of the table. However, in the case when a user rapidly changes the page, it keeps on refreshing with pages fluctuating between different page numbers and keeps on making continuous API requests.

2

Answers


  1. Maybe you should use an abort controller to cancel the previous request if the user rapidly changes pages. Also, you should update the dependency array because once any of these changes, a fetch request is called.

    const [isLoading, setIsLoading] = useState(false);
    const abortController = new AbortController();
    
    const fetchData = () => {
     setLoading(true);
     return axios
          .get(`${TRANSACTIONS_ENDPOINT}`, {
            params: {
              page: paginationConfig.pageNo,
              search_by: searchConfig.search_by,
              search_value: searchConfig.search_value
            },
            signal
          })
          .then((response) => {
            const { transactions, total_pages, page} = response.data;
    
            setTransactions(transactions);
            setPaginationConfig({
              ...paginationConfig,
              pageNo: page,
              totalPages: total_pages,
            });
            sessionStorage.setItem(PAGE_STORAGE_KEY, page.toString());
          })
          .catch((err) => {
            console.error(err);
          })
          .finally(() => setLoading(false))
    }
    
    useEffect(() => {
      // Reject if it surpasses 10 s
       Promise.race([
          fetchData(),
          new Promise((_, reject) => setTimeout(reject, 10_000)),
       ]).catch(() => {
          controller.abort();
       });
    
       return () => {
          if (controller.signal.aborted) {
            controller.abort();
          }
       };
    }, [paginationConfig.pageNo, searchConfig.search_by, searchConfig.search_value]);
    
    
    Login or Signup to reply.
  2. You just need to add a cleanup function at the end of useEffect.

    setup: The function with your Effect’s logic. Your setup function may also optionally return a cleanup function. When your component is added to the DOM, React will run your setup function. After every re-render with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. After your component is removed from the DOM, React will run your cleanup function.

      useEffect(() => {
        let flag = true;
        if(flag) {
          // do your Axios logic here
        }
        // cleanup ✅
        return () => {
          flag = false;
        };
      }, [paginationConfig.pageNo]);
    
    

    refs

    https://react.dev/reference/react/useEffect

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search