Open In App

Create a Quiz App using React Hooks and Timer-Based State Management

Last Updated : 23 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Quiz Application is a web-based application built using React Hooks and Timer-Based State Management. It provides users with a series of multiple-choice questions and requires them to select an option within a given time limit. If the user fails to select an option within the specified time, the application automatically moves to the next question.

Output Preview: Let us have a look at how the final output will look like.

Screenshot-(440)

Prerequisites / Technologies used:

Approach to create Quiz Application:

In this quiz app, we will be using React’s useState hook to manage various state variables to track the current quiz progress, score, and timer for each question.

QuestionBank component contains the questions which are rendered one by one once we click on the start quiz. Every question will have 10 sec of time to attempt. If user fails to attempt in given time, next question will be rendered automatically.

App component will conditionally render the different components based on state. Once we click on start quiz state will changed and Questions component will be rendered which will display the questions one by one. Once user reach to last question they can submit the test.

After submitting the test App component will render the Score component which is responsible to display the final score.

Steps to create the Quiz Application with Hooks:

Step 1: Create React Project

npx create-react-app quiz

Step 2: Navigate to project directory

cd quiz

Step 3: Installing required modules

npm install bootstrap

Step 4: Create a folder named Components in src folder and create new files QuestionBank.js, Questions.js and Score.js

Project Structure:Screenshot-(442)

The updated dependencies in package.json file will look like:

"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"bootstrap": "^5.3.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}

Example:Below is the implementation of the Quiz App. Here we have created some components.

  • App.js: This is the primary Component for quiz app project, where we’ve defined all the functions necessary for the quiz app’s logic.
  • QuestionBank.js: This file contains an array of objects of questions. Every object have question, options array and the correct answer.
  • Questions.js: This component will be rendering individual questions in the quiz app. It receives the question data as props and displays the question along with multiple-choice options and the timer for each question.
  • Score.js: This component is responsible to display the final score once we submit the test.

Javascript




// App.js
 
import React, { useState, useEffect } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import qBank from "./Components/QuestionBank";
import Questions from './Components/Questions';
import Score from './Components/Score';
 
const App = () => {
   const [questions, setQuestions] = useState(qBank);
   const [currentQuestion, setCurrentQuestion] = useState(0);
   const [score, setScore] = useState(0);
   // set time for each question
   const [timer, setTimer] = useState(10);
   const [quizStarted, setQuizStarted] = useState(false);
   const [isLastq, setIsLastq]=useState(false)
 
  useEffect(() => {
    if (quizStarted) {
      const interval = setInterval(() => {
        setTimer(prevTimer => {
          if (prevTimer > 0) {
            return prevTimer - 1;
          } else {
            setCurrentQuestion(prevQuestion => prevQuestion + 1);
             // Reset timer for the next question
            return 10;
          }
        });
      }, 1000);
       
      return () => clearInterval(interval);
    }
  }, [currentQuestion, quizStarted]);
 
  const handleAnswerClick = (selectedAnswer) => {
      if (selectedAnswer === questions[currentQuestion].answer) {
            setScore(prevScore => prevScore + 1);
      }
  };
 
  const handleNextQuestion=()=>{
    if (currentQuestion + 2 === questions.length) {
        setIsLastq(true)
    }
    setCurrentQuestion(prevQuestion => prevQuestion + 1);
    setTimer(10);
  }
 
  const startQuiz = () => {
    setQuizStarted(true);
  };
 
  return (
 
    <div className="card container mt-2
         d-flex justify-content-center
         align-items-center"
         style={{ maxWidth: '600px', margin: '0 auto' }}>
      <h1 className="text-success mt-2">GeekForGeeks</h1>
      <h3 className=" mt-2">Quiz App</h3>
      <div>
         
        {!quizStarted ? (
          <div>
            <div className="card-body">
                <h2 className="card-title">Start Test</h2>
                <button className="btn btn-primary"
                   onClick={startQuiz}>
                   Start Test
                </button>
            </div>
          </div>
         ) : currentQuestion < questions.length ? (
          <Questions
              questions={questions}
              handleNextQuestion={handleNextQuestion}
              currentQuestion={currentQuestion}
              handleAnswerClick={handleAnswerClick}
              timer={timer}
              isLastq={isLastq}
          />
        ) : (
          <Score
             score={score}
             setScore={setScore}
             setCurrentQuestion={setCurrentQuestion}
             setQuizStarted={setQuizStarted}
             setIsLastq={setIsLastq}
             setTimer={setTimer}           
          />
        )}
      </div>
    </div>
  );
};
 
export default App;


Javascript




// QuestionBank.js
 
const questions = [
    {
        question: 'What is the capital of India?',
        options: ['Mumbai', 'Pune', 'Nagpur', 'Delhi'],
        answer: 'Delhi',
        id:1
    },   
    {
      question: 'Who is the Prime Minister of India?',
      options: ['Rahul Gandhi', 'Nitin Gadkari',
             'Narendra Modi', 'Sharad Pawar'],
      answer: 'Narendra Modi',
      id:2
    },
 
      {
        question: 'when India got independence?',
        options: ['1950', '1947', '1930', '1945'],
        answer: '1947',
        id:3
      },
 
  ];
  export default questions;


Javascript




// Questions.js
 
import React, { useState } from 'react';
 
const Questions = ({ questions,
                     handleNextQuestion,
                     currentQuestion,
                     handleAnswerClick, timer, isLastq }) => {
     const optionIds = ['A', 'B', 'C', 'D'];
     const [selectedOption, setSelectedOption] = useState(null);
     
    const handleOptionClick = (option) => {
        setSelectedOption(option);
        handleAnswerClick(option);
    };
     
    return (
        <div className="container mt-3 bg-light">
            <div>
                <div className="card-body">
                    <p className="mt-2 text-warning">
                       Time remaining: {timer}
                    </p>
                    <h4 className="card-text">
                       {  questions[currentQuestion].id}{') '}
                       {  questions[currentQuestion].question}
                    </h4>
                    <div className="list-group">
                        
                          questions[currentQuestion].options
                                                      .map((option, index) => (
                            <button
                                key={index}
                                className= { `list-group-item
                                    list-group-item-action
                                    mt-2 ${
                                        selectedOption === option ? 'active' : ''
                                    }`}
                                    onClick={() => handleOptionClick(option)}
                                    style={{
                                      backgroundColor:
                                      selectedOption === option ?
                                          'lightblue' : 'white',
                                      border: '1px solid gray' }}
                             >
                                {optionIds[index]}{')'} {option}
                            </button>
                        ))}
                    </div>
                    <br/>
                    <div className="row">
                        <div className="col">
                            <p className="card-title">
                                Question {currentQuestion + 1}
                                    of {questions.length}
                            </p>
                        </div>
                        <div className="col">
                            {  isLastq?(
                               <button className="btn btn-primary btn-sm"
                                    onClick={handleNextQuestion}>
                                    Submit
                               </button>
 
                            ):(
                               <button className="btn btn-primary btn-sm"
                                     onClick={handleNextQuestion}>
                                     Next Question
                               </button>
                            )}
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
};
 
export default Questions;


Javascript




// Score.js
 
import React from 'react'
 
const Score = ({ score, setScore,
               setCurrentQuestion, setQuizStarted,
               setIsLastq, setTimer}) => {
    return (
      <div>
          <div className="card-body">
              <h2 className="card-title">Quiz Completed!</h2>
              <h4 className="card-text">Your score: {score}</h4>
              <button className="btn btn-primary"
                    onClick={() => { setCurrentQuestion(0);
                        setScore(0); setQuizStarted(true);
                        setIsLastq(false); setTimer(10);}}>
                        Restart Quiz
              </button>
           </div>
      </div>
    )
}
 
export default Score;


Steps to run the application:

Step 1: Run the quiz application server by below command

npm start

Step 2: We can access our application on below URL

localhost:3000

Output:

Animation



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads