Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
In this article, we will create a Quiz app in react. This Quiz game will be usual like other Quiz game. Here we will have some questions along with 4 options and scorecard. After answering all questions, the result will be appeared, and lastly we will have a button to restart the quiz.
So basically this is going to be a beginner-friendly project, so let’s make this project step-by-step.
Let’s start with a little hard code, in return() statement, for questions, we have added a header tag for name of quiz, then another heading for score. Then, after we have hard coded our question and its options in the question card. And then lastly we have added result card where we have again hard coded correct answers and a restart button. This is just the beginning of the app, so it is right now hard coded, but we will improve this code after adding CSS.
return (
<div className="App">
{/* 1. Header */}
<h1>USA Quiz</h1>
{/* 2. Current Score */}
<h2>Score: 0</h2>
{/* 3. Show results or show the question game */}
{/* Final Results */}
{/* 5. Question Card */ }
<div className="question-card">
{/* Current Question */}
<h2>
Question: 2 out of 5
</h2>
<h3 className="question-text">What is the capital of America?</h3>
{/* List of possible answers */}
<ul>
<li>New York City</li>
<li>Boston</li>
<li>Santa Fe</li>
<li>Washington DC</li>
</ul>
</div>
<div className="final-results">
<h1>Final Results</h1>
<h2>
1 out of 5 correct - (
20%)
</h2>
<button onClick={() => restartGame()}>Restart game</button>
</div>
</div>
);
Now, before making it dynamic, let’s add some CSS. We won’t go deeper with CSS because it’s not a big deal for us, nor it’s too hard to understand, so we just copy and paste it.
.App {
text-align: center;
}
.question-card {
/* Center the div */
margin: 0 auto;
/* Dimensions */
width: 80%; /* Can be in percentage also. */
height: auto;
/* Visual */
background-color: gray;
padding: 16px;
border-radius: 16px;
color: white;
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px,
rgba(0, 0, 0, 0.3) 0px 18px 36px -18px;
}
ul {
list-style: none;
}
li {
margin-top: 8px;
background-color: darkgray;
padding: 16px;
border: 3px solid white;
border-radius: 20px;
font-size: 20px;
}
.question-text {
color: darkblue;
font-size: 24px;
}
/* Final Results */
.final-results {
/* Center the div */
margin: 0 auto;
/* Dimensions */
width: 50%; /* Can be in percentage also. */
height: auto;
margin-top: 64px;
/* Visual */
background-color: gray;
padding: 16px;
border-radius: 16px;
color: white;
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px,
rgba(0, 0, 0, 0.3) 0px 18px 36px -18px;
}
button {
background-color: red; /* Green */
border: none;
color: white;
padding: 16px 24px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
font-weight: bold;
border-radius: 24px;
}
Now let’s begin by removing the result part from the question screen, for that we have just added a state showResult
with initial value false. Then we are using ternary condition on result and question card where if showResult
is false then question card will be visible and if showResult
is true then result card will show up.
const [showResults, setShowResults] = useState(false);
return (
<div className="App">
{/* 1. Header */}
<h1>USA Quiz</h1>
{/* 2. Current Score */}
<h2>Score: 0</h2>
{/* 3. Show results or show the question game */}
{/* Final Results */}
{showResults? (
<div className="final-results">
<h1>Final Results</h1>
<h2>
1 out of 5 correct - (
20%)
</h2>
<button onClick={() => restartGame()}>Restart game</button>
</div>
) : (
<div className="question-card">
{/* Current Question */}
<h2>
Question: 2 out of 5
</h2>
<h3 className="question-text">What is the capital of America?</h3>
{/* List of possible answers */}
<ul>
<li>New York City</li>
<li>Boston</li>
<li>Santa Fe</li>
<li>Washington DC</li>
</ul>
</div>
)}
</div>
);
Now let’s add Questions, we have made a component named Questions.js component, we have added questions array in which we have added text property with a question and another property is options where we added 4 options with IDs, and also we have added isCorrect
property with boolean values true and false.
const questions = [
{
text: "What is the capital of America?",
options: [
{ id: 0, text: "New York City", isCorrect: false },
{ id: 1, text: "Boston", isCorrect: false },
{ id: 2, text: "Santa Fe", isCorrect: false },
{ id: 3, text: "Washington DC", isCorrect: true },
],
},
{
text: "What year was the Constitution of America written?",
options: [
{ id: 0, text: "1787", isCorrect: true },
{ id: 1, text: "1776", isCorrect: false },
{ id: 2, text: "1774", isCorrect: false },
{ id: 3, text: "1826", isCorrect: false },
],
},
{
text: "Who was the second president of the US?",
options: [
{ id: 0, text: "John Adams", isCorrect: true },
{ id: 1, text: "Paul Revere", isCorrect: false },
{ id: 2, text: "Thomas Jefferson", isCorrect: false },
{ id: 3, text: "Benjamin Franklin", isCorrect: false },
],
},
{
text: "What is the largest state in the US?",
options: [
{ id: 0, text: "California", isCorrect: false },
{ id: 1, text: "Alaska", isCorrect: true },
{ id: 2, text: "Texas", isCorrect: false },
{ id: 3, text: "Montana", isCorrect: false },
],
},
{
text: "Which of the following countries DO NOT border the US?",
options: [
{ id: 0, text: "Canada", isCorrect: false },
{ id: 1, text: "Russia", isCorrect: true },
{ id: 2, text: "Cuba", isCorrect: true },
{ id: 3, text: "Mexico", isCorrect: false },
],
},
];
export default questions;
Now for questions, we have added a state for currentQuestion
with initial 0 value and another state for score with initial 0 value. Then in return(), we have to modify score value with the value of state. Then in question card, we have added dynamic heading using <h2>Question: {currentQuestion + 1} out of {questions.length}</h2>
.
After that, we have fetched the question using this questions[currentQuestion].text
line of code. Now to fetch option, we have used map method to fetch every option, here we have used fetched the text of option using key value. And all options contain onClick event with a function call.
In this function, we have to increase the score value if isCorrect
is true, and we will add another question by increasing the value of setCurrentQuestion. For example, if currentQuestion value is 1 then <h3 className="question-text">{questions[currentQuestion].text}</h3>
this code will run and 1 question will be displayed, and if we increase the value of currentQuestion using setCurrentQuestion then we will get a 2nd question in that same div.
Basically, as soon we hit click on any option, then question will get changed till the last question.
const [currentQuestion, setCurrentQuestion] = useState(0);
const [score, setScore] = useState(0);
const optionClicked = (isCorrect) => {
// Increment the score
if (isCorrect) {
setScore(score + 1);
}
if (currentQuestion + 1 < questions.length) {
setCurrentQuestion(currentQuestion + 1);
} else {
setShowResults(true);
}
};
return (
<div className="App">
{/* 1. Header */}
<h1>USA Quiz 🇺🇸</h1>
{/* 2. Current Score */}
<h2>Score: {score}</h2>
{/* 3. Show results or show the question game */}
{showResults ? (
/* 4. Final Results */
<div className="final-results">
<h1>Final Results</h1>
<h2>
{score} out of {questions.length} correct - (
20%)
</h2>
<button onClick={() => restartGame()}>Restart game</button>
</div>
) : (
/* 5. Question Card */
<div className="question-card">
{/* Current Question */}
<h2>
Question: {currentQuestion + 1} out of {questions.length}
</h2>
<h3 className="question-text">{questions[currentQuestion].text}</h3>
{/* List of possible answers */}
<ul>
{questions[currentQuestion].options.map((option) => {
return (
<li
key={option.id}
onClick={() => optionClicked(option.isCorrect)}
>
{option.text}
</li>
);
})}
</ul>
</div>
)}
</div>
);
Now we are on the last stage of the quiz app, here in result part we have did some basic modification to get score value on the result div, and we have used (score / questions.length) * 100}%
to calculate the percentage of result. Then we have added a function on restart button, in this function we have just reset all state values back to 0 and false.
const restartGame = () => {
setScore(0);
setCurrentQuestion(0);
setShowResults(false);
};
<div className="final-results">
<h1>Final Results</h1>
<h2>
{score} out of {questions.length} correct - (
{(score / questions.length) * 100}%)
</h2>
<button onClick={() => restartGame()}>Restart game</button>
</div>
App.js
import React, { useState } from "react";
import "./App.css";
function App() {
// Properties
const [showResults, setShowResults] = useState(false);
const [currentQuestion, setCurrentQuestion] = useState(0);
const [score, setScore] = useState(0);
// Helper Functions
/* A possible answer was clicked */
const optionClicked = (isCorrect) => {
// Increment the score
if (isCorrect) {
setScore(score + 1);
}
if (currentQuestion + 1 < questions.length) {
setCurrentQuestion(currentQuestion + 1);
} else {
setShowResults(true);
}
};
/* Resets the game back to default */
const restartGame = () => {
setScore(0);
setCurrentQuestion(0);
setShowResults(false);
};
return (
<div className="App">
{/* 1. Header */}
<h1>USA Quiz 🇺🇸</h1>
{/* 2. Current Score */}
<h2>Score: {score}</h2>
{/* 3. Show results or show the question game */}
{showResults ? (
/* 4. Final Results */
<div className="final-results">
<h1>Final Results</h1>
<h2>
{score} out of {questions.length} correct - (
{(score / questions.length) * 100}%)
</h2>
<button onClick={() => restartGame()}>Restart game</button>
</div>
) : (
/* 5. Question Card */
<div className="question-card">
{/* Current Question */}
<h2>
Question: {currentQuestion + 1} out of {questions.length}
</h2>
<h3 className="question-text">{questions[currentQuestion].text}</h3>
{/* List of possible answers */}
<ul>
{questions[currentQuestion].options.map((option) => {
return (
<li
key={option.id}
onClick={() => optionClicked(option.isCorrect)}
>
{option.text}
</li>
);
})}
</ul>
</div>
)}
</div>
);
}
export default App;
Questions.js
const questions = [
{
text: "What is the capital of America?",
options: [
{ id: 0, text: "New York City", isCorrect: false },
{ id: 1, text: "Boston", isCorrect: false },
{ id: 2, text: "Santa Fe", isCorrect: false },
{ id: 3, text: "Washington DC", isCorrect: true },
],
},
{
text: "What year was the Constitution of America written?",
options: [
{ id: 0, text: "1787", isCorrect: true },
{ id: 1, text: "1776", isCorrect: false },
{ id: 2, text: "1774", isCorrect: false },
{ id: 3, text: "1826", isCorrect: false },
],
},
{
text: "Who was the second president of the US?",
options: [
{ id: 0, text: "John Adams", isCorrect: true },
{ id: 1, text: "Paul Revere", isCorrect: false },
{ id: 2, text: "Thomas Jefferson", isCorrect: false },
{ id: 3, text: "Benjamin Franklin", isCorrect: false },
],
},
{
text: "What is the largest state in the US?",
options: [
{ id: 0, text: "California", isCorrect: false },
{ id: 1, text: "Alaska", isCorrect: true },
{ id: 2, text: "Texas", isCorrect: false },
{ id: 3, text: "Montana", isCorrect: false },
],
},
{
text: "Which of the following countries DO NOT border the US?",
options: [
{ id: 0, text: "Canada", isCorrect: false },
{ id: 1, text: "Russia", isCorrect: true },
{ id: 2, text: "Cuba", isCorrect: true },
{ id: 3, text: "Mexico", isCorrect: false },
],
},
];
export default questions;
App.css
.App {
text-align: center;
}
.question-card {
/* Center the div */
margin: 0 auto;
/* Dimensions */
width: 80%; /* Can be in percentage also. */
height: auto;
/* Visual */
background-color: gray;
padding: 16px;
border-radius: 16px;
color: white;
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px,
rgba(0, 0, 0, 0.3) 0px 18px 36px -18px;
}
ul {
list-style: none;
}
li {
margin-top: 8px;
background-color: darkgray;
padding: 16px;
border: 3px solid white;
border-radius: 20px;
font-size: 20px;
}
.question-text {
color: darkblue;
font-size: 24px;
}
/* Final Results */
.final-results {
/* Center the div */
margin: 0 auto;
/* Dimensions */
width: 50%; /* Can be in percentage also. */
height: auto;
margin-top: 64px;
/* Visual */
background-color: gray;
padding: 16px;
border-radius: 16px;
color: white;
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px,
rgba(0, 0, 0, 0.3) 0px 18px 36px -18px;
}
button {
background-color: red; /* Green */
border: none;
color: white;
padding: 16px 24px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
font-weight: bold;
border-radius: 24px;
}
Check out awesome video of Quiz App in React: