javascriptreactjs

useReFetch is not a function or its return value is not iterable


import { useRef, useState, useEffect } from 'react'

function useReFetch(url, interval) {   
  const [data, setData] = useState(null);   
  const [loading, setloading] = useState(true);   
  const [error, seterror] = useState(null);   
  let timeRef = useRef(null);
   
  async function fetchdata() {
    setloading(true);

    try {
      const resp = await fetch(url);
      const result = await resp.json();
      setData(result);
    } catch(error) {
      seterror(error);
    } finally {
      setloading(false);
    }
  }

  useEffect(()=> {
    fetchdata();

    if (interval !== null) {
      timeRef.current = setInterval(fetchdata, interval);
      
      return() => {
        clearInterval(timeRef);
      }   
    }
  }, [url, interval])   

  return { data, error, loading };
} 

function App() {   
  const [url, seturl] = useState("https://jsonplaceholder.typicode.com/todos/1")  
  const [data, error, loading] = useReFetch(url, 5000);   

  return (
    <div>
      <h1>{data}</h1>
    </div>
  )
} 

export default App;

Above is the custom hook for refetching the details again and again from backend and when I try to open it in my browser it's showing this error --useReFetch is not a function or its return value is not iterable.


Solution

  • There are couple of issues with your code. The first is coming from how you're returning your data from the useReFetch custom hook and how you're retrieving the data from the custom hook in the App component. You're return an object with { data, error, loading } but you're destructuring your useRefetch() hook as an array and that is why you're getting that error. Instead, you should destructure your useRefetch hook as follows:

    const { data, error, loading } = useReFetch(url, 5000);   
    

    Also, you do not need to have your url in a state variable. It's very unnecessary since the url state doesn't change. Instead, you should pass your url directly to your useRefetch() hook:

     const { data, error, loading } = useReFetch("https://jsonplaceholder.typicode.com/todos/1, 5000);
    

    Additionally, your api endpoint returns a single object data and you're rendering it directly into your JSX. React is going to throw error in this instance. Instead, you should probably just target one of the properties of the returned data like this:

    function App(){   
    //The rest of your state
      return (
        <div>
          <h1>{data.title}</h1>
        </div>
      )
    
    } 
    

    And if you want to see the structure of the entire dataset, you can just stringify the object as follows:

    function App(){   
    //The rest of your state
      return (
        <div>
          <h1>{JSON.stringify(data)}</h1>
        </div>
      )
    
    }