what if fetch statement never returns response?

I’m curious about the following:

First question is more of a confirmation. If the response takes 3 seconds to come back, will the app just display nothing for the first 3 seconds? And then the data after it’s re-rendered due to the fact that useEffect will trigger it because it’s a dependency?

Second, what if the data never loads? Will there just be an empty div (nothing displayed) or will the program crash?

import './MyProjects.css'
import {useState, useEffect, useRef} from 'react'

const MyProjects = () => {
    const [data, setData] = useState([])
    const [dataLoaded, setDataLoaded] = useState(false)
    let clone = useRef(null);

    const mapNewProperty = (item, color) => {
        return {...item, backgroundColor: color}
    }

    async function fetchData() {
        await fetch('https://jsonplaceholder.typicode.com/todos')
        .then(response => response.json())
        .then(json => {
            setData(json)
            clone.current = [...json]
            setDataLoaded(true)
        })
        // .then(setData(data.map((item) => ({...item, backgroundColor: true}))))
        .catch((err) => {
            console.log(err);
          });
    }

    useEffect(() => {
        fetchData()
    }, [])

    useEffect(() => {
        if (!dataLoaded) return
        const newArray = clone.current.map(item => mapNewProperty(item, 'red'));
        // console.log(clone.current)
        setData([...newArray])
        console.log(data)
    }, [dataLoaded]);


  return (
    <div className='project-container'>
        {data.length > 0 && (
                <div className='data-container'>
                {data.map(item => (
                    <div key={item.id} style={{backgroundColor : item.backgroundColor}} onClick={() => {
                    }}
                    className='dataItem'>{item.title}</div>
                ))}
                </div>
        )}
    </div>
  )
}

export default MyProjects

>Solution :

The logic for what the app will display is right there in the code. See the initial default value for data:

const [data, setData] = useState([])

It’s an empty array. And see the display logic:

<div className='project-container'>
    {data.length > 0 && /* etc... */}
</div>

So, if data.length is not > 0 (if the array is empty), then this containing <div> will be empty. This is true both before and after data has loaded.

If what you’re looking for is some kind of UI indication that data is currently loading, you can add that:

<div className='project-container'>
    {!dataLoaded && <div>Loading...</div>}
    {data.length > 0 && /* etc... */}
</div>

If you also want some kind of UI indication that data has loaded but is still empty, you can add that:

<div className='project-container'>
    {!dataLoaded && <div>Loading...</div>}
    {(dataLoaded && data.length === 0) && <div>No data found!</div>}
    {data.length > 0 && /* etc... */}
</div>

Basically, whatever you want to conditionally render in the UI, you would just define that condition.

Leave a Reply