Search code examples
javascriptreactjsreact-hooksuse-effectuse-state

My useState variable throws cannot read length of undefined


I'm implementing pagination where I have a useState variable which I change with a change in page number, below is the code where I use two useEffects to call the data of pagenumber and pagenumber+1 to check if it throws a 404 so I know when to stop displaying the next button.

useEffect(() => {
    
        async function fetchData() {
            try {
                const baseUrl = 'https://gateway.marvel.com:443/v1/public/characters';
                const url = baseUrl + '?ts=' + ts + '&apikey=' + publickey + '&hash=' + hash+ '&limit=100&offset='+parseInt(pageNumber)*50;
                const { data } = await axios.get(url);
                setCharactersData(data.data.results);
                setLoading(false);
            } catch (e) {
                setCharactersData([]);
                console.log(e);
            }
        }
        
        fetchData();
    }, [ pageNumber ]);


    
    useEffect(() => {
    
        async function fetchData() {
            try {
                const baseUrl = 'https://gateway.marvel.com:443/v1/public/characters';
                const url = baseUrl + '?ts=' + ts + '&apikey=' + publickey + '&hash=' + hash+ '&limit=100&offset='+(parseInt(pageNumber)+1)*50;
                const { data } = await axios.get(url);
                console.log(data);
                setNewData(data.data.results);
                setLoading(false);
            } catch (e) {
                setNewData([]);
                console.log(e);
            }
        }
        
        fetchData();
    }, [ pageNumber ]);

Return part:

return (
            <div>
                { parseInt(pageNumber)!==0 && <Link className='characterlink1' to={`/characters/page/${parseInt(pageNumber)-1}`}>
                        Previous
                    </Link>}
                    
                    { charactersData.length===0 && <Four />}

                 { newData.length>0 && <Link className='characterlink2' to={`/characters/page/${parseInt(pageNumber)+1}`}>
                        Next
                    </Link>}
            

This was working fine until I added the lines:

  1. setCharactersData([]); in catch block of first useEffect.
  2. { charactersData.length===0 && } in the return part.

I added these lines to add a 404 page if the url has a pagenumber which is larger than the available pagenumbers. When I do this I get an error saying:

TypeError: Cannot read properties of undefined (reading 'length')

The weird part is that I don't see this error until I change the url 3-4 times.


Solution

  • You're changing your state in a catch block, which is not how you're supposed to change your state. Instead, I would say it is better to try initialize your state with the empty array so that the length property always exists, thus removing the error. Such a thing can be done like this:

    const [charactersData, setCharactersData] = useState([]);
    

    Or with the type of the charactersData (yay typescript)

    const [charactersData, setCharactersData] = useState<charactersDataType>([]);