code_dude
code_dude

Reputation: 1111

How can I make react's useEffect to stop rerender in an infinite loop?

So I am working on a small personal project that is a todo app basically, but with a backend with express and mongo. I use useEffect() to make an axios get request to the /all-todos endpoint that returns all of my todos. Then inside of useEffect()'s dependency array I specify the todos array as dependency, meaning that I want the useEffect() to cause a rerender anytime the tasks array gets modified in any way. Take a look at this:

export default function () {
    const [todos, setTodos] = useState([]);
    const currentUser = JSON.parse(localStorage.getItem('user'))._id;

    useEffect(() => {
        function populateTodos () {
            axios.get(`http://localhost:8000/api/all-todos/${currentUser}`)
                .then(res => setTodos(res.data))
                .catch(err => console.log(err));
        }

        populateTodos();
    }, [todos]);

    console.log(todos);

    return (
        <div className="App">
            ...
        </div>
    );
}

So I placed that console.log() there to give me a proof that the component gets rerendered, and the problem is that the console.log() gets printed to the console forever, until the browser gets slower and slower. How can I make it so that the useEffect() gets triggered obly when todos gets changed?

Upvotes: 0

Views: 323

Answers (1)

Rashomon
Rashomon

Reputation: 6762

You should execute the hook only if currentUser changes:

export default function () {
    const [todos, setTodos] = useState([]);
    const [error, setError] = useState(null);

    const currentUser = JSON.parse(localStorage.getItem('user'))._id;

    useEffect(() => {
        function populateTodos () {
            axios.get(`http://localhost:8000/api/all-todos/${currentUser}`)
                .then(res => setTodos(res.data))
                .catch(err => setError(err));
        }

        populateTodos();
    }, [currentUser]);

    console.log(todos);

    if (error) return (
        <div className="App">
            There was an error fetching resources: {JSON.stringify(error)}
        </div>
    )

    return (
        <div className="App">
            ...
        </div>
    );
}

Upvotes: 1

Related Questions