I have this simple website where I fetch data and get an array of Obj, and display it on the Quiz page, but I also implement a countdown. The problem is that every time the timer renders the fetch run again and I get a different array every sec. How Do I prevent the initial obj I fetch from changing?
Im getting the fetch array from useContext
const Quiz = () =>{
useEffect(() => {
countDown();
}, [num]);
let timer;
const countDown = () => {
if (num > 0) {
timer = setTimeout(() => {
setNum(num - 1);
}, 1000);
}
if(num === 0){
nextQuestion()
}
return num;
};
return(...)
}
CodePudding user response:
You need to remove the num from the dependency array of useEffect.
When you add a dependency to useEffect it will re render every time it changes, and you only want countDown to run once.
Usually you should also wrap the countDown component with useCallback and put the countDown as a dependency on the useEffect
anyway, for now this should solve your issue -
const Quiz = () =>{
useEffect(() => {
countDown();
}, []);
let timer;
const countDown = () => {
if (num > 0) {
timer = setTimeout(() => {
setNum(num - 1);
}, 1000);
}
if(num === 0){
nextQuestion()
}
return num;
};
return(...)
}
CodePudding user response:
does this answer your question ?
import React, { useState, useEffect } from "react";
const questionsList = [
{ question: "Sum of 4 4 ?" },
{ question: "Sum of 10 10 ?" }
];
export default function CountDown() {
const [counter, setCounter] = useState(10);
const [currentQuestion, setCurrentQuestion] = useState(0);
useEffect(() => {
const timeInterval = setInterval(() => {
counter > 0 && setCounter((prevCount) => prevCount - 1);
}, 1000);
if (counter === 0 && currentQuestion 1 !== questionsList.length) {
setCurrentQuestion((prevQues) => prevQues 1);
setCounter(10);
}
return () => {
clearInterval(timeInterval);
};
}, [counter]);
return (
<>
<h1>CountDown {counter}</h1>
<h1>
{counter !== 0 ? (
<>
{" "}
Question number {currentQuestion 1}
{" --> "}
{questionsList?.[currentQuestion]?.question}
</>
) : (
<h1>Test Ended </h1>
)}
</h1>
</>
);
}