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
CodePudding user response:
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.
CodePudding user response:
To answer your first question, only the container component will render until your data.length
no longer is 0. To have a better looking UI/UX, I would suggest looking into creating a skeleton loader.
A fetch will eventually timeout (defaults are usually around 30 seconds, but others do exist) and return an error. Since you have a catch statement, it will log the error to the console. After that nothing will happen since you are not rendering anything on an error.
You could potentially have another state that is for errors and then render components based on that similar yo your data.length &&
code.
CodePudding user response:
For the first question, the app should display an empty div for the 3 seconds.
For the second question, the app will keep displaying an empty div forever. It has no reason to crash. The react code just depends on what is in the state. If it never changes, what is displayed will also never change.
The request however is not infinite. It will timeout soon causing just an error to be displayed in the console