4

I'm calling an Api to get data but the data is really heavy. I'm wondering if i'm calling it in right place inside useEffect or should i call it somewhere else. I've put the console.log to check but the number of console.log exceeded the number of objects i have in the API. My code is :

const ProductsList = () => {
  const [products, setProducts] = useState([]);
  const [isLoading, setLoading] = useState(true);

  useEffect(() => {
    let isMounted = true;
    getProducts().then((response) => {
      if (isMounted) {
        console.log('im being called');
        setProducts(response);
        setLoading(false);
      }
    });
    return () => { isMounted = false; };
  }, [products]);

  return (
    <View style={styles.container}>
      {isLoading ? <ActivityIndicator /> : ((products !== [])
          && (
          <FlatList
            data={products}
            keyExtractor={(item, index) => index.toString()}
            renderItem={({ item }) => {
              return (
                <Item
                  style={{ marginLeft: 35 }}
                  name={item.name}
                  date={item.date}
                  address={item.adress}
                />
              );
            }}
          />
          )
      )}
    </View>
  );
};
Abdo Rabah
  • 1,670
  • 2
  • 15
  • 31
  • Yeah, it seems correct. But if you don't have any errors and are only interested in having somebody look at your code, then visit [codereview.stackexchange.com](https://codereview.stackexchange.com/). It's a great community with people willing to give you detailed feedback on potential improvements. – Emiel Zuurbier Dec 17 '20 at 21:46

1 Answers1

3

It looks like your effect goes round in a circle:

  1. On each render the effect will look at products to see if it has changed.

  2. If it has changed it will call your effect which fetches new products.

  3. When you get new products you update your products state.

  4. This causes the effect to run again.

You probably only want to run that effect once, when the component mounts. In which case you can simply write:

  useEffect(() => {
    getProducts().then((response) => {
      setProducts(response);
      setLoading(false);
    });
  }, []); // <-- note the empty array, which means it only runs once when mounted

If that single API call is too heavy, then you need to look more at things like pagination in your requests, or modifying the response to return only the data you really need. But that's outside the scope of this question, I think.

Let me know if you have any questions.

Flagship1442
  • 1,688
  • 2
  • 6
  • 13
  • Thank you for you answer. that's exactly what it's going on. The effect doesn't stop running. I added the `isMounted` from a solution https://stackoverflow.com/questions/53949393/cant-perform-a-react-state-update-on-an-unmounted-component i've found because i was getting this Warning: Can't perform a React state update on an unmounted component. – Abdo Rabah Dec 17 '20 at 21:58
  • Oh ok. Does that work with the isMounted variable? I guess I can see it now you explained. If the answer is otherwise correct would you mind accepting it? Thanks! – Flagship1442 Dec 17 '20 at 22:03