Search code examples
javascriptreactjsfetch-api

Fetch method in useEffect is in infinite loop


I was getting the infinite loop of the code getting executed, but I couldn't find where the problem was. As I am new with react I sometimes struggle to see the problem. Could it be the dependency or that I forgot to close something off?

import {useCookies} from "react-cookie";
import React, {useEffect, useState} from "react";
import CircularProgress from "@mui/material/CircularProgress";
import {Navigate} from "react-router-dom";

const Date = () => {

    const [cookies] = useCookies(['XRSF-TOKEN']);
    const [loading, setloading] = useState(false);
    const [error, seterror] = useState(false);
    const [users, setusers] = useState([]);

    useEffect(() => {
        setloading(true);
        fetch("/allotherusers", {credentials: "include"})
            .then(response => response.text())
            .then(body => {
                if (body === '') {
                    return <Navigate to="/" />
                }
                else {
                    setusers(JSON.parse(body));
                }
                setloading(false);
            });
    }, [setusers, setloading])

    const userlist = users.map(user => {
        return (
            <div>
                <p> {user.firstname}</p>
                <button onClick={() => like(user, false)}>Like</button>
            </div>
        )
    });

    const like = async (likeduser, superlike) => {
        const likemodel = 
            {
            likeduser: likeduser,
            superlike: superlike

        }

        await fetch('/liked', {
            method: 'POST',
            headers: {
                'X-XSRF-TOKEN': cookies['XRSF-TOKEN'],
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(likemodel),
            credentials: 'include'
        });
    };


    return (
        <div>
            {userlist}
        </div>
    );

}
export default Date;

Here you see how the frontend is keep calling the API the request:

Backend api


Solution

  • inside of your effect function, when you do setusers(JSON.parse(body)) and setloading(false) you are updating userData to a new array. Even if all the items inside of that new array are exactly the same, the reference to the new userData array has changed, causing the dependencies of the effect to differ, triggering the function again -- ad infinitum.

    One simple solution is to simply remove setusers from the dependency array. In this way, the useEffect function basically acts similar to componentDidMount in that it will trigger once and only once when the component first renders.

     useEffect(() => {
        setloading(true);
        fetch("/allotherusers", {credentials: "include"})
            .then(response => response.text())
            .then(body => {
                if (body === '') {
                    return <Navigate to="/" />
                }
                else {
                    setusers(JSON.parse(body));
                }
                setloading(false);
            });
    }, [])
    

    I think you should try this.!