Im making a quiz app. Currently i can switch to the next question by answering (clicking a button). Also, when timer expires (10 secs for each question) it automatically switches to the next question (timer
resets to default state) regardless of button clicked or no. Above mentioned things works and its fine.
However I made a timer as a seperate child component to avoid unneccesary rerenders of parent component. The problem is that when i click a button to answer the question timer
does not reset (but it should) to its default state value (10secs). I dont know how to communicate between child (Timer) and parent component (App), because i dont wanna initialize that timer
state in parent component and put it in handleAnswerCorrectness
so when currentPage
changes i also reset timer
, because it would cause parent rerender each second and lose sense of making it a child component.
How to do it properly???
const {useState, useEffect} = React;
const questions = [
{
questionText: "What is the capital city of France",
answerOptions: [
{ id: 1, answerText: "New York", isCorrect: false },
{ id: 2, answerText: "London", isCorrect: false },
{ id: 3, answerText: "Paris", isCorrect: true },
{ id: 4, answerText: "Dublin", isCorrect: false }
]
},
{
questionText: "Who is CEO of Tesla?",
answerOptions: [
{ id: 1, answerText: "Jeff Bezos", isCorrect: false },
{ id: 2, answerText: "Elon Musk", isCorrect: true },
{ id: 3, answerText: "Bill Gates", isCorrect: false },
{ id: 4, answerText: "Tony Stark", isCorrect: false }
]
}
];
const App = () => {
const [currentPage, setCurrentPage] = useState(0);
const handleAnswerCorrectness = () => {
if (currentPage + 1 < questions.length) {
setCurrentPage((prevState) => prevState + 1);
}
};
return (
<div className="App">
<div>
<h3>
Question {currentPage + 1}/{questions.length}
</h3>
<Timer
currentPage={currentPage}
onCurrentPageChange={setCurrentPage}
questionsLenght={questions.length}
/>
</div>
<p>{questions[currentPage].questionText}</p>
<div>
{questions[currentPage].answerOptions.map((answerOption) => (
<button key={answerOption.id} onClick={handleAnswerCorrectness}>
{answerOption.answerText}
</button>
))}
</div>
</div>
);
}
const Timer = ({
onCurrentPageChange,
currentPage,
questionsLenght
}) => {
const [timer, setTimer] = useState(10);
useEffect(() => {
const interval = setInterval(() => {
if (timer > 0) {
setTimer((prevState) => prevState - 1);
}
if (timer === 0 && currentPage + 1 < questionsLenght) {
onCurrentPageChange((prevState) => prevState + 1);
setTimer(10);
}
}, 1000);
return () => clearInterval(interval);
}, [timer]);
return (
<div>
<span>{timer}</span>
</div>
);
};
const root = ReactDOM.createRoot(
document.getElementById("root")
).render(<App/>);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>