Search code examples
javascriptreactjsreact-custom-hooks

isLoading not working when changing state in custom hook


I am using a custom useFetch function, the isLoading function is working if the window reloads but when i change the state with useState hooks, the custom hooks works but isLoading is not working.

-

const [url, setUrl] = useState('/api')
    const [name, setName] = useState("random");

    
const filterChoice = (e) => {
  const value = document.getElementById('filter').value;
  setUrl(`/top/${value}`)
  setName(value)
} 

const { data: anime, error, isLoading, total } = useFetch(url)
<select name="sort"  className='sort' id="filter" onChange={filterChoice}>
    <option value="random">filter</option>
    <option value="airing">Top Airing</option>
    <option value="upcoming">Top Upcoming</option>
    <option value="popularity">Top By popularity</option>
 </select>

useFetch

import { useState, useEffect } from 'react';

const useFetch = (url) => {
    const [data, setData] = useState(null);
    const [isLoading, setIsLoading] = useState(true);
    const [error, setError] = useState(null);
    const [total, setTotal] = useState(0)

    useEffect(() => {
        const abortCont = new AbortController();

        fetch(url)
            .then((res) => {
                if (!res.ok) {
                    throw Error('could not fetch the data for that resource')
                } else {
                    return res.json()
                }
            })
            .then((data) => {
                if (data.length === 0) {
                    throw Error('no anime available')
                }
                setData(data)
                setTotal(data.length)
                setIsLoading(false)
                setError(null)
            })
            .catch((err) => {
                if (err.name === 'AbortError') {
                    console.log('Fetch aborted')
                }
                setIsLoading(false)
                setError(err.message)
            })
        return () => abortCont.abort()
            
    },[url])
    return {data,isLoading,error,total}
}
 
export default useFetch;
I think everything works great in useFetch but could be wrong


Solution

  • Inside useEffect, before making the fetch call, you have to reset the isLoading state value. Have modified the code. Let me know if it works.

     import { useState, useEffect } from 'react';
        
        const useFetch = (url) => {
            const [data, setData] = useState(null);
            const [isLoading, setIsLoading] = useState(true);
            const [error, setError] = useState(null);
            const [total, setTotal] = useState(0)
        
            useEffect(() => {
                const abortCont = new AbortController();
                setIsLoading(true); // This line was missing
        
                fetch(url)
                    .then((res) => {
                        if (!res.ok) {
                            throw Error('could not fetch the data for that resource')
                        } else {
                            return res.json()
                        }
                    })
                    .then((data) => {
                        if (data.length === 0) {
                            throw Error('no anime available')
                        }
                        setData(data)
                        setTotal(data.length)
                        setIsLoading(false)
                        setError(null)
                    })
                    .catch((err) => {
                        if (err.name === 'AbortError') {
                            console.log('Fetch aborted')
                        }
                        setIsLoading(false)
                        setError(err.message)
                    })
                return () => abortCont.abort()
                    
            },[url])
            return {data,isLoading,error,total}
        }
         
        export default useFetch;