Hire the author: Maduka C

Fast learner, hard worker and team player who is looking for an opportunity to contribute to projects and also enhance her skills.

Introduction

In this article, we will learn how to build a quiz app. However, this project will contain a not only the quiz section but also a section that provides us with fun facts about the main topic which is in this case the earth in addition to the quiz section. I decided to create this project so I could better learn React and the concept of fetching data using an API call in React. Now I’m going to teach you how to do the same. We will be creating this using a popular JavaScript library React, style with Material UI, and deploy to Heroku. The source code of this project is also available on GitHub through this link.

Glossary

React: According to Wikipedia, React is a free and open-source front-end JavaScript library for building user interfaces based on reusable UI components. It’s used for handling the view layer for web and mobile apps. The main purpose of React is to be fast, scalable, and simple. Hence why I choose to create this project with it.

Material UI: As defined in this article, Material-UI is a library that allows us to import and use different components to create a user interface in our React applications. This saves a significant amount of time since we do not need to write all the CSS codes from scratch.

Heroku: Heroku is a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud. It supports several programming languages.

Creating our react-app

Now having said all that, it’s time to start creating our project. The first step will be to install Node on your local server (assuming you do not have it installed already). To install Node follow the steps in this article. Having installed Node successfully on our device, we will go ahead to set up React by running this command in our terminal

npx create-react-app earthQuizApp

Here, ‘earthQuizApp’ is the name of the project. Feel free to rename it to anything you like. Once we run this command, a folder with the name “earthQuizApp” will be created on our computer and all of the packages it requires will be automatically installed. This process usually takes about 3 minutes or more. Be sure to give it time. Once our project has been created, we will see a bunch of files and folders. We’ll be working majorly with the ‘src’ folder. Within the src folder create another folder and name it components. This folder will hold the four components we will have in our project. Create a file within the component folder and name it ‘Home.js’ (This will be the home page). Create two more files and name them ‘learn.js (where information about the earth will be displayed) and ‘quiz.js’ (quiz component) respectively. Then create the last one for the NavBar and name it ‘ResponsiveAppBar.js’.

NB: To view the project in the browser run this code in the terminal

npm start

Step 1:

The first step is to create a AppBar. This component will handle our navigation. Let’s name it ResponsiveAppBar.js. We will use be using Material UI’s (Responsive) AppBar component. We’ll customize it to our taste by adding a little inline styling. We will also export it to make it available for use in other components. Paste this code in the ResponsiveAppBar.js file

Step 2:

The next step is to create our home page. It is the first page users will see when they visit our web app. It will consist of

  • Navbar
  • Heading
  • An Image
  • Some Write-up
  • Two Buttons

We’ll import the necessary Material UI components. Paste the following code in the Home.js

import React from "react";
import ResponsiveAppBar from "./ResponsiveAppBar";
import {useNavigate} from "react-router-dom";
import Grid from '@mui/material/Grid';
import Typography from "@mui/material/Typography";
import Avatar from "@mui/material/Avatar";
import Button from "@mui/material/Button";
import img from "./../assets/images/earth.jpg";
const Home = (props) => {
let navigate = useNavigate();
return (
<div>
<ResponsiveAppBar />
<Typography variant="h6" component="div"
style={{
marginTop:50,
paddingTop: 50,
fontWeight:600,
fontSize:32,
textAlign:'center',}}>
EARTH
</Typography>
<Grid container justifyContent="center">
<Avatar
variant={"rounded"}
alt="The Earth"
src={img}
style={{
width: 200,
height: 200,
marginTop:20,
}}
/>
<br />
<Typography variant="h6" component="div" align="center">
Earth apart from being our home, has a lot of cool fun facts you are
probably not aware of. Not to worry, we are gonna get to know some of
these facts today. Click the Learn button to start or the Quiz button
to check how much you already know.
</Typography>
<div component="span">
<Button variant="contained" color="error" onClick={() => navigate("/Quiz")}>
Quiz
</Button>
</div>
</Grid>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center'}}>
<Button variant="contained" color="error" onClick={() => navigate('/Learn')}>
Learn
</Button>
</div>
</div>
);
};
export default Home;
view raw Home.js hosted with ❤ by GitHub

Step 3:

The next step is to create our JSON files where information will be pulled from. There will be three of them namely

  • facts.json (information that will be displayed in Learn component will be contained here)
  • credit.json (sources where the information in facts.json was gotten from)
  • quiz.json (quiz questions and answers will be contained here)

In the src folder, create another folder and name it sources. This is where our JSON files will be created in.

facts.json

Place the following code in this file. You can also replace them with your own if you wish

[
{
"id": "1",
"title": "Earth Doesn’t Take 24 Hours to Rotate on its Axis",
"content": "It actually takes 23 hours, 56 minutes and 4 seconds for the Earth to rotate once completely on its axis, which astronomers refer to as a Sidereal Day. Now wait a second, doesn’t that mean that a day is 4 minutes shorter than we think it is? You’d think that this time would add up, day by day, and within a few months, day would be night, and night would be day."
},
{
"id": "2",
"title": "Earth is 4.5 Billion Years Old",
"content": "How do we know this? In order to find out the age of the Earth, scientists look at rock and sediment and try to determine the age of that piece of sediment. It's not as easy as one may think, however. The processes of plate tectonics mean that the Earth is constantly recycling its rock, breaking it down into magma in the interior before pumping it back up to the surface once more."
},
{
"id": "3",
"title": "How fast does the earth orbit the sun per hour?",
"content": " the earth is moving about the sun in a very nearly circular orbit. It covers this route at a speed of nearly 30 kilometers per second, or 67,000 miles per hour."
},
{
"id": "4",
"title": "70% of the Earth’s Surface is Covered in Water",
"content": "When astronauts first went into the space, they looked back at the Earth with human eyes for the first time. Based on their observations, the Earth acquired the nickname the “Blue Planet:. And it’s no surprise, seeing as how 70% of our planet is covered with oceans. The remaining 30% is the solid crust that is located above sea level, hence why it is called the “continental crust”"
},
{
"id": "5",
"title": "Highest Temperature",
"content": "The highest recorded temperature on Earth is 134 degrees Fahrenheit. It was recorded at Greenland Ranch in Death Valley, California, on July 10, 1913."
},
{
"id": "6",
"title": "A year on Earth isn’t 365 days",
"content": "It’s actually 365.2564 days. It’s this extra .2564 days that creates the need for a Leap Year once ever four years. That’s why we tack on an extra day in February every four years – 2004, 2008, 2012, etc. The exceptions to this rule is if the year in question is divisible by 100 (1900, 2100, etc), unless it divisible by 400 (1600, 2000, etc)"
},
{
"id": "7",
"title": "Lowest Temperature",
"content": "The lowest recorded temperature on Earth is -128.5 degrees Fahrenheit. It was recorded at Vostok, Antarctica, on July 21, 1983."
},
{
"id": "8",
"title": "Earth is Mostly Iron, Oxygen and Silicon",
"content": "If you could separate the Earth out into piles of material, you’d get 32.1 % iron, 30.1% oxygen, 15.1% silicon, and 13.9% magnesium. Of course, most of this iron is actually located at the core of the Earth. If you could actually get down and sample the core, it would be 88% iron. And if you sampled the Earth’s crust, you’d find that 47% of it is oxygen."
},
{
"id": "9",
"title": "The Earth’s Atmosphere Extends to a Distance of 10,000 km",
"content": "Earth’s atmosphere is thickest within the first 50 km from the surface or so, but it actually reaches out to about 10,000 km into space. It is made up of five main layers – the Troposphere, the Stratosphere, the Mesosphere, the Thermosphere, and the Exosphere."
},
{
"id": "10",
"title": "Earth is Almost a Sphere",
"content": "Many people tend to think that the Earth is a sphere. In fact, between the 6th century BCE and the modern era, this remained the scientific consensus. But thanks to modern astronomy and space travel, scientists have since come to understand that the Earth is actually shaped like a flattened sphere (aka. an oblate spheroid)"
}
]
view raw facts.json hosted with ❤ by GitHub

credit.json

The following code will go into this file.

[
{
"First": "Universetoday",
"Second": "ThoughtCo",
"Last": "Scientificamerican"
}
]
view raw credit.json hosted with ❤ by GitHub

quiz.json

This file will contain the following code

[
{
"id": "1",
"question":"Earth moving around the sun at ____________ per hour",
"answers": ["670,000 miles","67,000 miles", "6,700 miles", "670 miles"],
"correctAnswer": "67,000 miles"
},
{
"id": "2",
"question":"Earth is Mostly Comprised of the following except ________",
"answers": ["Iron", "Air", "Silicon", "Oxygen"],
"correctAnswer": "Air"
},
{
"id": "3",
"question":"The highest recorded temperature on Earth is ________",
"answers": ["134 degrees Fahrenheit", "34 degrees Fahrenheit", "20 degrees Fahrenheit", "160 degrees Fahrenheit"],
"correctAnswer": "134 degrees Fahrenheit"
},
{
"id": "5",
"question":"Earth is 4.5 Billion Years Old",
"answers": ["True", "False"],
"correctAnswer": "True"
},
{
"id": "6",
"question":"The lowest recorded temperature on Earth is _______",
"answers": ["128.5 degrees Fahrenheit", "0 degrees Fahrenheit", "-100.5 degrees Fahrenheit","-128.5 degrees Fahrenheit"],
"correctAnswer": "-128.5 degrees Fahrenheit"
},
{
"id": "7",
"question":"The Earth’s Atmosphere Extends to a Distance of 10,000 km",
"answers": ["False", "True", "Maybe"],
"correctAnswer": "True"
},
{
"id": "8",
"question":"A year on Earth is exactly ______ days ",
"answers": ["366", "365", "365.2564", "300"],
"correctAnswer": "365.2564"
},
{
"id": "9",
"question":"",
"answers": ["nearly 30 kilometers per second", "nearly 30 meters per second", "nearly 30 kilometers per minute", "nearly 30 meters per minute"],
"correctAnswer": "nearly 30 kilometers per second"
},
{
"id": "10",
"question":"Earth is Almost a Sphere",
"answers": ["True", "False", "I don't know"],
"correctAnswer": "True"
}
]
view raw quiz.json hosted with ❤ by GitHub

Step 4:

Having created all the JSON files we require for this project, the next step is to create our learning component. This is where those facts we talked about earlier will be displayed. To create this, paste the following lines of code into the learn.js file.

import React from "react";
import ResponsiveAppBar from "./ResponsiveAppBar";
import Typography from "@mui/material/Typography";
import { styled } from "@mui/material/styles";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Grid from "@mui/material/Grid";
import Facts from "../sources/facts.json";
import Data from "../sources/credits.json";
const Learn = () => {
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: theme.palette.mode === "dark" ? "#1A2027" : "#fff",
theme.typography.body2,
padding: theme.spacing(2),
textAlign: "center",
color: theme.palette.text.secondary,
}));
return (
<div>
<ResponsiveAppBar />
{Facts.map((fact, i) => (
<Box key={i} sx={{ flexGrow: 1 }} style={{
marginTop:50}} >
<Grid
container
spacing={2}
elevation={9}
justifyContent="center"
style={{ margin: "auto" }}
>
<Grid item xs={8} >
<Item>
<Typography
variant="h5"
gutterBottom
component="div"
style={{ fontWeight: 600 }}
>
{fact.id}. {fact.title}
</Typography>
<Typography variant="body1" gutterBottom>
{fact.content}
</Typography>
</Item>
</Grid>
</Grid>
<br />
<br />
</Box>
))}
{Data &&
Data.map((credit, i) => {
return (
<div key={i}>
<Grid container justifyContent="flex-end">
<Item>
<Typography variant="h5" gutterBottom component="div">
The information above was gotten from the following sources
</Typography>
<Typography variant="body1" gutterBottom>
{credit.First} <br />
{credit.Second}
<br />
{credit.Last}
</Typography>
</Item>
</Grid>
</div>
);
})}
</div>
);
};
export default Learn;
view raw Learn.js hosted with ❤ by GitHub

Step 5:

The next step is to create the Quiz.js. This component will display the quizzes, the various options, and also scores at the end of the quiz

import React from "react";
import ResponsiveAppBar from "./ResponsiveAppBar";
import {useNavigate} from "react-router-dom";
import { useState } from "react";
import Quest from "../sources/quiz.json";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Button from "@mui/material/Button";
import Grid from "@mui/material/Grid";
import Radio from "@mui/material/Radio";
import RadioGroup from "@mui/material/RadioGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import FormControl from "@mui/material/FormControl";
import FormLabel from "@mui/material/FormLabel";
import { makeStyles } from "@material-ui/core/styles";
const Quiz = () => {
const [currentQuestion, setCurrentQuestion] = useState(0);
const [chosenAnswer, setChosenAnswer] = useState("");
const [score, setScore] = useState(0);
const [end, setEnd] = useState(false);
const [clickedAnswer, setClickedAnswer] = useState(false);
const checkAnswer = (answer) => {
setChosenAnswer(answer);
setClickedAnswer(true);
};
const checkCorrectAnswer = () => {
if (chosenAnswer === Quest[currentQuestion].correctAnswer) {
setScore(score + 1);
}
};
const finished = () => {
if (currentQuestion === Quest.length 1) {
setEnd(true);
}
};
const reset = () => {
setClickedAnswer(false);
};
const startOver = () => {
setCurrentQuestion(0);
setEnd(false);
setChosenAnswer("");
setScore(0);
};
let navigate = useNavigate();
const useStyles = makeStyles({
quizCard: {
margin: "auto",
padding: 10,
marginTop: 15,
color: "grey",
textAlign: "center",
},
buttonPrev: {
float: "left",
backgroundColor: "#fc4c4e",
},
buttonNext: {
float: "right",
},
totalAnswered: {
color: "red",
textAlign: "center",
paddingBottom: 10,
},
});
const classes = useStyles();
if (end) {
return (
<Card
sx={{ height: 335 }}
className={classes.quizCard}
>
<CardContent>
<Typography variant="h5" component="div" style={{
marginTop:50}}>
{`Good Work! Your Final Score is
${score}/${Quest.length}`}
</Typography>
<div style={{ padding: 20 }}>
<Button
variant="contained"
color="error"
className={classes.buttonNext}
onClick={() => startOver()}
>
Start over
</Button>
<Button
variant="contained"
color="error"
className={classes.buttonPrev}
onClick={() => navigate("/")}
>
Go Home
</Button>
</div>
</CardContent>
</Card>
);
} else
return (
<Grid container justifyContent="center" style={{
marginTop:50}} >
<ResponsiveAppBar />
<div>
<Card className={classes.quizCard} >
<CardContent>
<Typography
variant="body1"
gutterBottom
component="div"
textAlign="center"
>
<span className={classes.totalAnswered}>
{`${currentQuestion}/${Quest.length}`}
</span>
<br />
{Quest[currentQuestion].question}
</Typography>
</CardContent>
<Box>
{Quest[currentQuestion].answers.map((answer, i) => (
<FormControl
sx={{ m: 3 }}
variant="standard"
className={classes.ansOptions}
key={i}
>
<FormLabel
id="demo-radio-buttons-group-label"
></FormLabel>
<RadioGroup
aria-labelledby="demo-error-radios"
name="quiz"
value={chosenAnswer}
onClick={() => checkAnswer(answer)}
>
<FormControlLabel
value={answer}
name="answer"
control={<Radio />}
label={answer}
/>
</RadioGroup>
</FormControl>
))}
{clickedAnswer && (
<div>
{currentQuestion >= Quest.length 9 && (
<Button
variant="contained"
color="error"
className={classes.buttonPrev}
onClick={() => {
setCurrentQuestion(currentQuestion 1);
checkCorrectAnswer();
}}
>
Previous
</Button>
)}
{currentQuestion < Quest.length 1 && (
<Button
variant="contained"
color="error"
display="block"
className={classes.buttonNext}
onClick={() => {
setCurrentQuestion(currentQuestion + 1);
checkCorrectAnswer();
reset();
}}
>
Next
</Button>
)}
{currentQuestion === Quest.length 1 && (
<Button
variant="contained"
color="error"
display="block"
className={classes.buttonNext}
onClick={() => finished()}
>
FINISH
</Button>
)}
</div>
)}
</Box>
</Card>
</div>
</Grid>
);
};
export default Quiz;
view raw Quiz.js hosted with ❤ by GitHub

Step 6;

Finally, To set up our ‘App.js’. Paste in the following code

import React from 'react';
import { BrowserRouter, Link, Route, Routes } from 'react-router-dom'
import Home from './component/Home';
import Quiz from './component/Quiz';
import Learn from './component/Learn';
view raw App.js hosted with ❤ by GitHub

The first line imports React, and the second line imports BrowserRouter, Link, Route, and Routes from ‘react-router-dom’ all of which are needed to navigate to the various components in our project. The last three lines import the different components present. Lastly, Place the following code within the return statement

<div className="App">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/learn" element={<Learn />} />
<Route path="/quiz" element={<Quiz />} />
</Routes>
</div>
view raw App.js hosted with ❤ by GitHub

Deployment

To deploy this project to Heroku follow the steps below:

  • Push the code to an existing or new Github repository.
  • Go to (Heroku’s official website) and create an account and log in to the dashboard.
  • Before deploying the app go to:
  • Heroku dashboard > settings > buildpacks > add buildpacks and then add https://github.com/mars/create-react-app-buildpack.git
  • While in the dashboard, go to create new app, enter the App name, choose a region and click the create app button.
  • Under deployment method choose Github, connect your Github account and choose the repo where your code is and connect.
  • Enable Automatic deployment and click deploy branch.
  • Give it a few minutes and your app will be ready. The link to your app will also be displayed.

If you do all these with no errors you will come up with a project like this: Earth-Quiz-App

Learning Tools

Some of the resources that helped me with this project include:

Learning Strategy

Stackoverflow was of immense help to me while creating this quiz app. If you run into errors at any stage, I suggest you ask questions in the comment section, alternatively search for that exact error in StackOverflow or post it as a new question, someone on the platform will most likely be of help.

Reflective Analysis

Creating this Project taught me a lot, like what Material UI is and how to use it, how to work with JSON data, how to use the map function, and finally the difference between useEffect (although not used in this project) and useState hook. While useState allows functional component to have state, useEffect on the other hand allows functional component to have a lifecycle. Another react hook used in this project is the useNavigate and it is used for navigation. Working on this project made me appreciate the concept of React.js more.

Conclusion

Thank you for reading and I hope this article will be able to help anyone who wishes to create a similar project. Let me point out that this project is open to improvement. An Idea will be to add a login system so that each user has his scores recorded and displayed on login (if he already completed the quiz at least once). Please feel free to add any other features. Also, if you are looking for other project ideas you can build with React please, check out this article

The code is also available on GitHub through this link.

Hire the author: Maduka C