title: Canceling an Axios REST call in React Hooks useEffects cleanup failing
body: <p>I'm obviously not cleaning up correctly and cancelling the axios GET request the way I should be.  On my local, I get a warning that says </p>
  
  <blockquote>
    <p>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.</p>
  </blockquote>
  
  <p>On stackblitz, my code works, but for some reason I can't click the button to show the error. It just always shows the returned data.</p>
  
  <p><a href="https://codesandbox.io/s/8x5lzjmwl8" rel="noreferrer">https://codesandbox.io/s/8x5lzjmwl8</a></p>
  
  <p>Please review my code and find my flaw.</p>
  
  <p>useAxiosFetch.js</p>
  
  <pre><code>import {useState, useEffect} from 'react'
  import axios from 'axios'
  
  const useAxiosFetch = url =&gt; {
      const [data, setData] = useState(null)
      const [error, setError] = useState(null)
      const [loading, setLoading] = useState(true)
  
      let source = axios.CancelToken.source()
      useEffect(() =&gt; {
          try {
              setLoading(true)
              const promise = axios
                  .get(url, {
                      cancelToken: source.token,
                  })
                  .catch(function (thrown) {
                      if (axios.isCancel(thrown)) {
                          console.log(`request cancelled:${thrown.message}`)
                      } else {
                          console.log('another error happened')
                      }
                  })
                  .then(a =&gt; {
                      setData(a)
                      setLoading(false)
                  })
          } catch (e) {
              setData(null)
              setError(e)
          }
  
          if (source) {
              console.log('source defined')
          } else {
              console.log('source NOT defined')
          }
  
          return function () {
              console.log('cleanup of useAxiosFetch called')
              if (source) {
                  console.log('source in cleanup exists')
              } else {
                  source.log('source in cleanup DOES NOT exist')
              }
              source.cancel('Cancelling in cleanup')
          }
      }, [])
  
      return {data, loading, error}
  }
  
  export default useAxiosFetch
  </code></pre>
  
  <p>index.js</p>
  
  <pre><code>import React from 'react';
  
  import useAxiosFetch from './useAxiosFetch1';
  
  const index = () =&gt; {
      const url = "http://www.fakeresponse.com/api/?sleep=5&amp;data={%22Hello%22:%22World%22}";
      const {data,loading} = useAxiosFetch(url);
  
      if (loading) {
          return (
              &lt;div&gt;Loading...&lt;br/&gt;
                  &lt;button onClick={() =&gt; {
                      window.location = "/awayfrom here";
                  }} &gt;switch away&lt;/button&gt;
              &lt;/div&gt;
          );
      } else {
          return &lt;div&gt;{JSON.stringify(data)}xx&lt;/div&gt;
      }
  };
  
  export default index;
  </code></pre>