简体   繁体   中英

React useEffect() Infinite loop

I was trying to replicate a personal project to set a Spinner loader while the data fetch is being load but I got another error before.

I was reading in other questions like this one , that in order to avoid a useEffect() infinite loop I have to add an empty array to the end, but still it doesn't work.

This is my code, it just re-renders infinitely despite the empty array added.

src/components/Users.js

import React, { useState, useEffect, useContext } from "react";
import GlobalContext from "../context/Global/context";

export default () => {
  const context = useContext(GlobalContext);
  const [users, setUsers] = useState([]);

  async function getUsers() {
    context.setLoading(true);
    const response = await fetch("https://jsonplaceholder.typicode.com/users");
    if (response.ok) {
        context.setLoading(false);
        const data = await response.json();
        setUsers(data);
    } else {
        console.error('Fetch error');
    }
  }

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

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

This is the non-working Sandbox , I am not sure why this is happening, any comments are appreciated.

The problem is you keep mounting and then umounting the Users component. The <App> renders, and loading is false, so it renders <Users> . Since Users rendered its effect gets run which immediately sets loading to true.

Since loading is now true, <App> rerenders, and no longer has a <Users> component. You have no teardown logic in your effect, so the fetch continues, and when it's done, it sets loading to false and sets users to the data it got. Trying to set users actually results in this error in the console, which points out that Users is unmounted:

proxyConsole.js:64 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
    in _default (at App.js:25)

And now that loading has been set to false, the process repeats.

The solution to this is to have the data loading be in a component that stays mounted. Either change App to not unmount Users, or move the fetching up to App and pass the data as a prop.

I think the issue is because of

context.setLoading(false);

just remove this line from your getUsers function and add a separate useEffect hook.

useEffect(() => {
   context.setLoading(false);
}, [users]) //Run's only when users get changed

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM