简体   繁体   中英

re-rendering issue using react hooks

Learning React Hooks, I am developing a testing app. My app loads data from an API and then populates a grid. Piece of kake. The problem shows up when I try to show a loading indicator. It enters in a re-render loop. Here is what I did:

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

function MyComp(props) {
   const [loading, setLoading] = useState(false);
   const [info, setInfo] = useState(null);

   useEffect(() => {
      setLoading(!loading);

      const getData = response => {
         if (response.response) {
            setInfo(response.response);
         } else {
            console.log('there was an error');
         }
         setLoading(!loading);
      };

      fetch(URL, {})
        .then(resp => ({ getData({response: resp}))
        .catch(error => ({ getData({ error });
   }, []);

   return (
     <>
        {loading ? "Loading" : "Not Loading"}
     </>
   );
}

export default MyComp;

What am I missing here?

You're setting loading in the useEffect hook. Changing a state causes the app to rerender which also you're infinitely doing in the useEffect. So once the app loads useEffect hook runs and changes loading, which again causes the app to re-render and the cycle continues.

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

function MyComp(props) {
   const [loading, setLoading] = useState(false);
   const [info, setInfo] = useState(null);

   useEffect(() => {
      setLoading(loading => !loading);

      const getData = response => {
         if (response) {
            setInfo(response);
         } else {
            console.log('there was an error');
         }
         setLoading(loading => !loading);
      };

      fetch(URL, {})
        .then(resp =>  getData( resp))
        .catch(error =>  getData(error));
   }, []);

   return (
     <>
        {loading ? "Loading" : "Not Loading"}
     </>
   );
}

export default MyComp;

After some "try and error" (I have to admit) I found this solution:

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

function MyComp(props) {
   const [loading, setLoading] = useState(false);
   const [info, setInfo] = useState(null);

   useEffect(() => {
      setLoading(false);
   }, [info]);

   function getData(response) {
      if (response.response) {
         setInfo(response.response);
      } else {
         console.log('there was an error');
      }
   }

   useEffect(() => {
      setLoading(true);

      fetch(URL, {})
        .then(resp => ({ getData({response: resp}))
        .catch(error => ({ getData({ error });
   }, []);

   return (
     <>
        {loading ? "Loading" : "Not Loading"}
     </>
   );
}

export default MyComp;

Maybe not the best, or prettiest, way... but it is working for me.

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