Open In App

Create a Quiz App with Next JS

In this article, we’ll explore the process of building a Quiz App utilizing NextJS. The quiz app provides users with a series of multiple-choice questions with options. Users can select the option and move to the next question. At the end, the user will be able to see the analysis of the quiz.

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



Prerequisites:

Approach to Create Quiz App with Next JS:

Steps to create the Quiz Application:

Step 1: Create a application of NextJS using the following command.

npx create-next-app@latest quiz-app

Step 2: Navigate to project directory



cd quiz-app

Step 3: Install the necessary package in your project using the following command.

npm install bootstrap

Project Structure:

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

"dependencies": {
"bootstrap": "^5.3.3",
"next": "14.1.0",
"react": "^18",
"react-dom": "^18"
}

Example: Below are the components which describes the basic implementation of the Quiz App.




// page.js
'use client'
import { useState } from "react";
import Quiz from "../Components/Quiz";
 
export default function Home() {
    const [quizStarted, setQuizStarted] = useState(false);
    const [name, setName] = useState('');
 
    return (
        <div className="container mt-5 ml-5">
            <div className="text-center">
 
                <h1 className='text-success mtb-1 '>
                    GeekForGeeks
                </h1>
                <h3 className='mb-4'>Quiz App</h3>
            </div>
 
            {quizStarted ? (
                <Quiz name={name} />
            ) : (
                <>
                    <div className="mb-3">
                        <label htmlFor="nameInput"
                            className="form-label">
                            Enter Your Name:
                        </label>
                        <input
                            type="text"
                            className="form-control"
                            id="nameInput"
                            value={name}
                            onChange={(e) =>
                                setName(e.target.value)}
                        />
                    </div>
                    <button
                        onClick={() => setQuizStarted(true)}
                        className="btn btn-primary"
                        // Disable button if name is empty or whitespace
                        disabled={!name.trim()}
                    >
                        Start Quiz
                    </button>
                </>
            )}
        </div>
    );
}




// QuestionSet.js
export const quiz = {
    questions: [
        {
            id: 1,
            question: 'What does API stand for?',
            answers: ['Application Programming Interface',
                'Advanced Programming Interface',
                'Application Program Interface',
                'Automated Programming Interface'],
            correctAnswer: 'Application Programming Interface',
        },
 
        {
            id: 3,
            question: `Which programming language is often
            used for building web servers?`,
            answers: ['Java', 'Python', 'JavaScript', 'C#'],
            correctAnswer: 'JavaScript',
        },
        {
            id: 4,
            question: 'What is the purpose of SQL?',
            answers: ['Styling web pages', 'Querying databases',
                'Creating animations', 'Developing mobile apps'],
            correctAnswer: 'Querying databases',
        },
        {
            id: 5,
            question: 'What does MVC stand for in web development?',
            answers: ['Model View Controller', 'Model Visual Controller',
                'Model View Component', 'Model Visual Component'],
            correctAnswer: 'Model View Controller',
        },
    ],
};




// Quiz.js
import React, { useState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { quiz } from '../Data/QuestionSet.js';
import ScoreCard from './ScoreCard.js';
 
const Quiz = ({ name }) => {
    const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
    const [selectedAnswer, setSelectedAnswer] = useState('');
    const [answerChecked, setAnswerChecked] = useState(false);
    const [selectedAnswerIndex, setSelectedAnswerIndex] = useState(null);
    const [showResults, setShowResults] = useState(false);
    const [quizResult, setQuizResult] = useState({
        score: 0,
        correctAnswers: 0,
        wrongAnswers: 0,
    });
 
    const { questions } = quiz;
    const { question, answers, correctAnswer } =
                                                questions[currentQuestionIndex];
 
    const onAnswerSelected = (answer, idx) => {
        setSelectedAnswerIndex(idx);
        setSelectedAnswer(answer);
        setAnswerChecked(true);
    };
 
    const handleNextQuestion = () => {
        if (selectedAnswer === correctAnswer) {
            setQuizResult((prev) => ({
                ...prev,
                score: prev.score + 5,
                correctAnswers: prev.correctAnswers + 1,
            }));
        } else {
            setQuizResult((prev) => ({
                ...prev,
                wrongAnswers: prev.wrongAnswers + 1,
            }));
        }
        if (currentQuestionIndex !== questions.length - 1) {
            setCurrentQuestionIndex((prev) => prev + 1);
        } else {
            setShowResults(true);
        }
        setSelectedAnswer('');
        setSelectedAnswerIndex(null);
        setAnswerChecked(false);
    };
 
    return (
        <div className='container mt-5'>
 
            <div>
                {!showResults ? (
                    <div className='card p-4'>
                        <h4>{question}</h4>
                        <ul className='list-group'>
                            {answers.map((answer, idx) => (
                                <li
                                    key={idx}
                                    onClick={() => onAnswerSelected(answer,idx)}
                                    className={
                                        'list-group-item ' +
                                        (selectedAnswerIndex ===
                                                idx ? 'active' : '') +
                                        ' cursor-pointer'
                                    }
                                >
                                    {answer}
                                </li>
                            ))}
                        </ul>
                        <div className='d-flex justify-content-between mt-3'>
                            <b>Question
                                {currentQuestionIndex + 1}/{questions.length}
                            </b>
                            <button
                                onClick={handleNextQuestion}
                                className='btn btn-primary'
                                disabled={!answerChecked}
                            >
                                {currentQuestionIndex === questions.length - 1 ?
                                    'Submit' : 'Next Question'}
                            </button>
                        </div>
                    </div>
                ) : (
                    <ScoreCard
                        quizResult={quizResult}
                        questions={questions}
                        name={name}
                    />
                )}
            </div>
        </div>
    );
};
 
export default Quiz;




// ScoreCard.js
import React from 'react';
 
const ScoreCard = ({ quizResult, questions, name }) => {
    const passPercentage = 60;
 
    const percentage = (quizResult.score / (questions.length * 5)) * 100;
    const status = percentage >= passPercentage ? 'Pass' : 'Fail';
 
    return (
        <>
            <div className='card p-4'>
                <h3>Hello, {name}. Here is your Result Analysis</h3>
                <table className='table'>
                    <tbody>
                        <tr>
                            <td>Total Questions:</td>
                            <td>{questions.length}</td>
                        </tr>
                        <tr>
                            <td>Total Score:</td>
                            <td>{quizResult.score}</td>
                        </tr>
                        <tr>
                            <td>Correct Answers:</td>
                            <td>{quizResult.correctAnswers}</td>
                        </tr>
                        <tr>
                            <td>Wrong Answers:</td>
                            <td>{quizResult.wrongAnswers}</td>
                        </tr>
                        <tr>
                            <td>Percentage:</td>
                            <td>{percentage}%</td>
                        </tr>
                        <tr>
                            <td>Status:</td>
                            <td>{status}</td>
                        </tr>
                    </tbody>
                </table>
                <button
                    onClick={() => window.location.reload()}
                    className='btn btn-primary mt-3'
                >
                    Restart
                </button>
            </div>
        </>
    );
};
 
export default ScoreCard;

Start your application using the following command.

npm run dev

Output: Naviage to the URL http://localhost:3000.


Article Tags :