
Creating a dynamic and engaging quiz application is an excellent project to enhance your ReactJS skills. In this tutorial, we’ll build an interactive quiz app using ReactJS that dynamically manages questions, tracks scores, and displays results.
Project Overview
Our quiz app will:
- Display multiple-choice questions.
- Track the user’s score.
- Show feedback on selected answers.
- Display results at the end with an option to restart.
Follow this video for complete guidance :
Getting Started
Ensure you have Node.js and npm installed. Create a new React app:
npx create-react-app quiz-app cd quiz-app npm start
Building the Quiz Component
Below is the complete code for our quiz component.
import React, { useState } from 'react'; function Quiz() { const questions = [ { question: 'What is React?', options: ['Library', 'Framework', 'Language', 'Tool'], answer: 'Library' }, { question: 'Who developed React?', options: ['Google', 'Facebook', 'Microsoft', 'Apple'], answer: 'Facebook' }, { question: 'Which hook manages state?', options: ['useEffect', 'useState', 'useContext', 'useReducer'], answer: 'useState' } ]; const [currentQuestion, setCurrentQuestion] = useState(0); const [score, setScore] = useState(0); const [showResult, setShowResult] = useState(false); const [selectedAnswer, setSelectedAnswer] = useState(null); const [isAnswered, setIsAnswered] = useState(false); const handleAnswer = (option) => { if (!isAnswered) { setSelectedAnswer(option); setIsAnswered(true); if (option === questions[currentQuestion].answer) { setScore(score + 1); } setTimeout(() => { const nextQuestion = currentQuestion + 1; if (nextQuestion < questions.length) { setCurrentQuestion(nextQuestion); setSelectedAnswer(null); setIsAnswered(false); } else { setShowResult(true); } }, 1000); } }; const resetQuiz = () => { setCurrentQuestion(0); setScore(0); setShowResult(false); setSelectedAnswer(null); setIsAnswered(false); }; const getButtonClass = (option) => { const baseClass = 'btn w-100 text-start p-3 mb-3 position-relative'; if (!isAnswered) return `${baseClass} btn-outline-primary`; if (option === questions[currentQuestion].answer) return `${baseClass} btn-success`; if (option === selectedAnswer) return `${baseClass} btn-danger`; return `${baseClass} btn-outline-secondary`; }; return ( <div className="min-vh-100 d-flex align-items-center justify-content-center bg-gradient" style={{ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' }}> <div className="container"> <div className="row justify-content-center"> <div className="col-12 col-md-8 col-lg-6"> <div className="card shadow-lg"> <div className="card-body p-4"> <h1 className="text-center mb-4"> <i className="fas fa-brain text-primary me-2"></i> Interactive Quiz </h1> {showResult ? ( <div className="text-center"> <i className="fas fa-trophy text-warning mb-4" style={{ fontSize: '4rem' }}></i> <h3 className="mb-3">Quiz Complete!</h3> <div className="display-4 text-primary mb-3"> {score} / {questions.length} </div> <p className="text-muted mb-4"> {score === questions.length ? 'Perfect score! Excellent work! ๐' : 'Good effort! Keep practicing! ๐ช'} </p> <button className="btn btn-outline-primary btn-lg" onClick={resetQuiz} > <i className="fas fa-redo-alt me-2"></i> Try Again </button> </div> ) : ( <div> <div className="mb-4"> <div className="progress mb-2" style={{ height: '8px' }}> <div className="progress-bar bg-primary" style={{ width: `${((currentQuestion + 1) / questions.length) * 100}%` }} ></div> </div> <small className="text-muted text-center d-block"> Question {currentQuestion + 1} of {questions.length} </small> </div> <h5 className="mb-4">{questions[currentQuestion].question}</h5> <div className="options"> {questions[currentQuestion].options.map((option) => ( <button key={option} onClick={() => handleAnswer(option)} className={getButtonClass(option)} disabled={isAnswered} > {option} {isAnswered && option === questions[currentQuestion].answer && ( <i className="fas fa-check position-absolute end-0 me-3 top-50 translate-middle-y"></i> )} </button> ))} </div> </div> )} </div> </div> </div> </div> </div> <style> {` body{ background:#f2f2f2; } .btn-outline-primary:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.1); } .btn { transition: all 0.3s ease; } .card { border-radius: 1rem; border: none; } .progress { border-radius: 1rem; background-color: #e9ecef; } .progress-bar { border-radius: 1rem; } `} </style> </div> ); } export default Quiz;
Explanation of the Code
State Management:
- currentQuestion: Tracks the current question index.
- score: Tracks correct answers.
- showResult: Toggles the result screen.
- selectedAnswer: Stores the user’s selected option.
- isAnswered: Prevents multiple clicks on the same question.
Answer Handling:
- Correct answers increase the score.
- Progresses to the next question after 1 second.
Dynamic Styling:
- Buttons change color based on the correctness of the selected answer.
Running the App
Start your development server:
npm start
Visit http://localhost:3000 to see your interactive quiz app.
This project demonstrates React’s core concepts, including state management, dynamic rendering, and event handling. You can extend the app by adding features like a timer, category filters, or a backend API for dynamic questions.
Happy coding! ๐