I'm making a loader for my React application in the form of a pizza that loses a piece every second.
When I refresh the page, my loader doesn't behave correctly. Images appear simultaneously.
Below is the code for my component:
import React, {useEffect, useState} from 'react';
import './Loader.css'
import pizza0 from '../../images/loader/pizza0.png'
import pizza1 from '../../images/loader/pizza1.png'
import pizza2 from '../../images/loader/pizza2.png'
import pizza3 from '../../images/loader/pizza3.png'
import pizza4 from '../../images/loader/pizza4.png'
import pizza5 from '../../images/loader/pizza5.png'
const Loader = () => {
const [imageStatus, setImageStatus] = useState({zero: true, first: false, second: false, third: false, fourth: false, fifth: false})
const [currentImage, setCurrentImage] = useState(0)
useEffect(() => {
setTimeout(() => action(), 1000);
const newCurrentImage = currentImage === 5 ? 0 : currentImage 1
setCurrentImage(newCurrentImage)
}, [imageStatus])
function action() {
switch (currentImage) {
case 0:
setImageStatus({...imageStatus, zero: false, first: true})
break;
case 1:
setImageStatus({...imageStatus, first: false, second: true})
break;
case 2:
setImageStatus({...imageStatus, second: false, third: true})
break;
case 3:
setImageStatus({...imageStatus, third: false, fourth: true})
break;
case 4:
setImageStatus({...imageStatus, fourth: false, fifth: true})
break;
case 5:
setImageStatus({...imageStatus, fifth: false, zero: true})
break;
}
}
function PizzaImg0() {
return (
<img src={pizza0} className={imageStatus.zero ? "pizza active" : "pizza"}/>
);
}
function PizzaImg1() {
return (
<img src={pizza1} className={imageStatus.first ? "pizza active" : "pizza"}/>
);
}
function PizzaImg2() {
return (
<img src={pizza2} className={imageStatus.second ? "pizza active" : "pizza"}/>
);
}
function PizzaImg3() {
return (
<img src={pizza3} className={imageStatus.third ? "pizza active" : "pizza"}/>
);
}
function PizzaImg4() {
return (
<img src={pizza4} className={imageStatus.fourth ? "pizza active" : "pizza"}/>
);
}
function PizzaImg5() {
return (
<img src={pizza5} className={imageStatus.fifth ? "pizza active" : "pizza"}/>
);
}
return (
<div>
<PizzaImg0/>
<PizzaImg1/>
<PizzaImg2/>
<PizzaImg3/>
<PizzaImg4/>
<PizzaImg5/>
</div>
);
};
export default Loader;
And very simple css
.pizza {
height: 120px;
display: none;
}
.pizza.active {
display: flex;
}
At the same time, if I switch to another tab or open an IDE and then return to the page, the loader works fine. What changes in terms of React when I leave and then return to the page? And what can I do to get rid of the problem?
CodePudding user response:
Trigger action method in a different useEffect when currentImage
changed
useEffect(() => {
const newCurrentImage = currentImage === 5 ? 0 : currentImage 1
setCurrentImage(newCurrentImage)
}, [imageStatus])
useEffect(() => {
setTimeout(() => action(), 1000);
}, [currentImage])
CodePudding user response:
You don't need to repeat creating your image tags. You can store the srcs in a ref since it's not going to change and it's not going to affect the render and have state for the active src. Something like this:
import React, { useEffect, useState, useRef } from 'react'
import './Loader.css'
import pizza0 from '../../images/loader/pizza0.png'
import pizza1 from '../../images/loader/pizza1.png'
import pizza2 from '../../images/loader/pizza2.png'
import pizza3 from '../../images/loader/pizza3.png'
import pizza4 from '../../images/loader/pizza4.png'
import pizza5 from '../../images/loader/pizza5.png'
const Loader = () => {
const imageSrcs = useRef([pizza0, pizza1, pizza2, pizza3, pizza4, pizza5])
const [currentImage, setCurrentImage] = useState(0)
useEffect(() => {
const timeoutId = setTimeout(() => {
setCurrentImage((prevValue) => (prevValue === 5 ? 0 : prevValue 1))
}, 1000)
return () => clearTimeout(timeoutId)
}, [])
return (
<div>
<img src={imageSrcs.current[currentImage]} className={'pizza active'} />
</div>
)
}
export default Loader