I bulit a timmer with useEffect and setInterval but this useEffect keep running the code that is out from useEffect and i don't want that
const [seconds,setSeconds] = useState(0)
const [minutes,setMinutes] = useState(15)
const { orderId } = useParams()
useEffect(()=>{
const interval = setInterval(() => {
if (seconds > 0) {
setSeconds(seconds => seconds - 1)
}
if (seconds === 0) {
if (minutes === 0) {
return () => clearInterval(interval)
} else {
setMinutes(minutes => minutes - 1)
setSeconds(59)
}
}
}, 1000)
return () => clearInterval(interval);
},[seconds,minutes])
useEffect(()=>{
if(minutes === 0 && seconds === 1 ){
//alert('hello guys ')
}
},[seconds,minutes])
console.log(orderId) //this console keep running every 1 second
even though it out from the useEffect
I don't want the code outside the useEffect to keep running
CodePudding user response:
This is the expected behavior. The purpose of calling a set state function (eg, setSeconds
or setMinutes
) is to cause the component to rerender. Your console.log statement is in the body of the component, so it will run every time the component rerenders. And since you're setting state every second, you are rerendering every second.
If you don't want to rerender the component then you could change your code to not set state. But by definition, since you aren't rerendering the component, then you aren't changing the time displayed to the user, so the user cannot tell that a countdown is happening. This could be used if you want to silently wait 15 minutes, and then do something at the end:
const ExampleComponent = () => {
// No need for state, since we won't be showing anything to the user
useEffect(() => {
const fifteenMinutes = 900000;
const id = setTimeout(() => {
alert('15 minutes have elapsed');
}, fifteenMinutes),
return () => clearTimeout(id);
}, []);
// ...
}