How to fix missing dependency warning when using useEffect React Hook?

前端 未结 13 1825
无人及你
无人及你 2020-11-22 03:14

With React 16.8.6 (it was good on previous version 16.8.3), I get this error when I attempt to prevent an infinite loop on a fetch request

./src/components/Bu         


        
相关标签:
13条回答
  • 2020-11-22 03:37

    These warnings are very helpful for finding components that do not update consistently: https://reactjs.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies.

    However, If you want to remove the warnings throughout your project, you can add this to your eslint config:

      {
      "plugins": ["react-hooks"],
      "rules": {
        "react-hooks/exhaustive-deps": 0
        }
      }
    
    0 讨论(0)
  • 2020-11-22 03:38

    This article is a good primer on fetching data with hooks: https://www.robinwieruch.de/react-hooks-fetch-data/

    Essentially, include the fetch function definition inside useEffect:

    useEffect(() => {
      const fetchBusinesses = () => {
        return fetch("theUrl"...
          // ...your fetch implementation
        );
      }
    
      fetchBusinesses();
    }, []);
    
    0 讨论(0)
  • 2020-11-22 03:39

    You can set it directly as the useEffect callback:

    useEffect(fetchBusinesses, [])
    

    It will trigger only once, so make sure all the function's dependencies are correctly set (same as using componentDidMount/componentWillMount...)


    Edit 02/21/2020

    Just for completeness:

    1. Use function as useEffect callback (as above)

    useEffect(fetchBusinesses, [])
    

    2. Declare function inside useEffect()

    useEffect(() => {
      function fetchBusinesses() {
        ...
      }
      fetchBusinesses()
    }, [])
    

    3. Memoize with useCallback()

    In this case, if you have dependencies in your function, you will have to include them in the useCallback dependencies array and this will trigger the useEffect again if the function's params change. Besides, it is a lot of boilerplate... So just pass the function directly to useEffect as in 1. useEffect(fetchBusinesses, []).

    const fetchBusinesses = useCallback(() => {
      ...
    }, [])
    useEffect(() => {
      fetchBusinesses()
    }, [fetchBusinesses])
    

    4. Disable eslint's warning

    useEffect(() => {
      fetchBusinesses()
    }, []) // eslint-disable-line react-hooks/exhaustive-deps
    
    0 讨论(0)
  • 2020-11-22 03:43

    you try this way

    const fetchBusinesses = () => {
        return fetch("theURL", {method: "GET"}
        )
          .then(res => normalizeResponseErrors(res))
          .then(res => {
            return res.json();
          })
          .then(rcvdBusinesses => {
            // some stuff
          })
          .catch(err => {
            // some error handling
          });
      };
    

    and

    useEffect(() => {
        fetchBusinesses();
      });
    

    it's work for you. But my suggestion is try this way also work for you. It's better than before way. I use this way:

    useEffect(() => {
            const fetchBusinesses = () => {
        return fetch("theURL", {method: "GET"}
        )
          .then(res => normalizeResponseErrors(res))
          .then(res => {
            return res.json();
          })
          .then(rcvdBusinesses => {
            // some stuff
          })
          .catch(err => {
            // some error handling
          });
      };
            fetchBusinesses();
          }, []);
    

    if you get data on the base of specific id then add in callback useEffect [id] then cannot show you warning React Hook useEffect has a missing dependency: 'any thing'. Either include it or remove the dependency array

    0 讨论(0)
  • 2020-11-22 03:44

    If you aren't using fetchBusinesses method anywhere apart from the effect, you could simply move it into the effect and avoid the warning

    useEffect(() => {
        const fetchBusinesses = () => {
           return fetch("theURL", {method: "GET"}
        )
          .then(res => normalizeResponseErrors(res))
          .then(res => {
            return res.json();
          })
          .then(rcvdBusinesses => {
            // some stuff
          })
          .catch(err => {
            // some error handling
          });
      };
      fetchBusinesses();
    }, []);
    

    If however you are using fetchBusinesses outside of render, you must note two things

    1. Is there any issue with you not passing fetchBusinesses as a method when it's used during mount with its enclosing closure?
    2. Does your method depend on some variables which it receives from its enclosing closure? This is not the case for you.
    3. On every render, fetchBusinesses will be re-created and hence passing it to useEffect will cause issues. So first you must memoize fetchBusinesses if you were to pass it to the dependency array.

    To sum it up I would say that if you are using fetchBusinesses outside of useEffect you can disable the rule using // eslint-disable-next-line react-hooks/exhaustive-deps otherwise you can move the method inside of useEffect

    To disable the rule you would write it like

    useEffect(() => {
       // other code
       ...
    
       // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []) 
    
    0 讨论(0)
  • 2020-11-22 03:44
    ./src/components/BusinessesList.js
    Line 51:  React Hook useEffect has a missing dependency: 'fetchBusinesses'.
    Either include it or remove the dependency array  react-hooks/exhaustive-deps
    

    It's not JS/React error but eslint (eslint-plugin-react-hooks) warning.

    It's telling you that hook depends on function fetchBusinesses, so you should pass it as dependency.

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

    It could result in invoking function every render if function is declared in component like:

    const Component = () => {
      /*...*/
    
      //new function declaration every render
      const fetchBusinesses = () => {
        fetch('/api/businesses/')
          .then(...)
      }
    
      useEffect(() => {
        fetchBusinesses();
      }, [fetchBusinesses]);
    
      /*...*/
    }
    

    because every time function is redeclared with new reference

    Correct way of doing this stuff is:

    const Component = () => {
      /*...*/
    
      // keep function reference
      const fetchBusinesses = useCallback(() => {
        fetch('/api/businesses/')
          .then(...)
      }, [/* additional dependencies */]) 
    
      useEffect(() => {
        fetchBusinesses();
      }, [fetchBusinesses]);
    
      /*...*/
    }
    

    or just defining function in useEffect

    More: https://github.com/facebook/react/issues/14920

    0 讨论(0)
提交回复
热议问题