Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I escape React useEffect infinite loop?

I wrote a code that receives the api through React Hook and calls the api again in the child component by passing the id when clicking. However, there seems to be a problem in settingState with arrow function in useEffect or onClick of child component.

I would appreciate it if you could give me an answer on how to fix it.

Users.js

import axios from 'axios';
import React, { useState, useEffect } from 'react';
import UserInfo from './UserInfo';


function Users() {
    const [users, setUsers] = useState(null)
    const [loding, setLoding] = useState(false)
    const [error, setError] = useState(false)


    const [userId, setUserId] = useState(null)

    const fetchUsers = async () => {
        try {
            setUsers(null)
            setError(null);
            setLoding(true)

            const respnse = await axios.get('https://jsonplaceholder.typicode.com/users')

            setUsers(respnse)
        } catch (e) {
            setError(e)
        }
        setLoding(false)
    };

    useEffect(() => {
        fetchUsers();
    }, []);

    if (loding) return <div>loading...</div>
    if (error) return <div>error....</div>
    if (!users) return null;

    return (
        <>
            <ul>
                {
                    users.data.map(user =>
                        <li key={user.id} onClick={() => setUserId(user.id)} >
                            {user.username} ({user.name})
                        </li>
                    )
                }
            </ul>
            <button onClick={fetchUsers}>
                reload
            </button>
            {userId && <UserInfo id={userId} />}
        </>
    );
}

export default Users;

UserInfo.js

import React, { useEffect, useState } from 'react';
import axios from 'axios';

function UserInfo({ id }) {

    const [userInfo, setUserInfo] = useState(null)

    async function getUsersAPI() {
        try {
            const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`)
            setUserInfo(response)
        } catch (e) {

        }
    }

    useEffect(() => {
        getUsersAPI()
    }, [userInfo])


    if (!userInfo) {
        return null;
    }

    const { data } = userInfo

    return (
        <>
            <h2>{data.username}</h2>
            <p>
                <b>email: </b>{data.email}
            </p>
        </>
    );
}

export default UserInfo;
like image 984
dev_O Avatar asked Jul 22 '26 10:07

dev_O


2 Answers

It seems like you want id to be a useEffect dependency instead of userInfo.

Otherwise every time userInfo changes the effect will run, it will call getUsersAPI which in turns sets the value of userInfo when axios resolves (thus causing an infinite loop).

    import React, { useEffect, useState } from 'react';
    import axios from 'axios';

    function UserInfo({ id }) {
        const [userInfo, setUserInfo] = useState(null)
        async function getUsersAPI() {
            try {
                const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${id}`)
                setUserInfo(response)
            } catch (e) {}
        }

        useEffect(() => {
            getUsersAPI()
        }, [id])

        if (!userInfo) {
            return null;
        }

        const { data } = userInfo

        return (
            <>
                <h2>{data.username}</h2>
                <p>
                    <b>email: </b>{data.email}
                </p>
            </>
        );
    }

    export default UserInfo;
like image 164
ksav Avatar answered Jul 24 '26 23:07

ksav


this problem is due to the fact that you have set userInfo as a dependency for useEffect dependency array! every time this component renders, useEffect will call your API and it changes the value of userInfo, so you encounter with infinite loop!

like image 21
Abbasihsn Avatar answered Jul 25 '26 00:07

Abbasihsn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!