React JS — QuizBee App

Daniel Xav De Oliveira
7 min readOct 28, 2019

These React JS blogs are a part of my personal journey with React JS.

This task involves calling an offline API and creating a Quiz Application. I think it is perfect practice for beginners and those looking to revise their knowledge. I followed this video tutorial from KnowledgeHut:

Getting Started

  • Ensure that you have Node.js installed on your PC. To check,

run npx — help. If a list of options is returned, you’re good. If not , please download Node.js.

  • Next , go into your desired directory ( or make one ) and run the following command to create your project,

create-react-app quizbee

  • Open the project you just created , called quizbee, using a text editor such as Visual Studio Code.

Setting up the Project

Open your newly created project, and you will see that the command create-react-app , created a scaffold of a React project for you. Nice !

Thereafter, go ahead and delete all the content within the src folder, as we will be creating the app from scratch. As mentioned we will be using an offline API for this project plus a style sheet. Please download those from this link now :

Once extracted, paste those asset files within the src folder of your project. Included, in the src folder you should create a file called index.js. This will be the root of the application.

In the index.js file , you should start by importing the React library and the component class because we will be building a class component which is subclassed from this component class. Since we are creating a web app, we need to import the React DOM library.

Furthermore import the style sheet we downloaded.

import React, { Component } from “react”;import ReactDOM from “react-dom”;import “./assets/style.css”;

Rendering the QuizBee Class

The next step is to create the root component class called QuizBee that extends the component class. This class will render a JSX template , that will render on the page.

import React, { Component } from “react”;import ReactDOM from “react-dom”;import “./assets/style.css”;class QuizBee extends Component {render() {return (<div className=”container”><div className=”title”>QuizBee</div></div>);}}ReactDOM.render(<QuizBee />, document.getElementById(“root”));

We then invoke the render method from the React DOM library , using our root component class as the first argument and also a selector to an element in our HTML file ( public/index.html) where-in we render the element.

<body><div id=”root”></div></body></html>

In your terminal, if you navigate to your projects directory and run npm start you should see the following in the page that pops up in your default browser:

Fetching the data from the API

Begin, by importing into your index.js the quizService module as follows:

import quizService from ‘./quizService’;

Moreover, instantiate a local state for this component , and in questionBank is where the question data will be stored that comes from the API.

state = {questionBank: []};

Next, we create a function getQuestions that calls the quizService API and populates questionBank state variable with the results.

getQuestions = () =>{quizService().then(question => {this.setState({questionBank: question});});};

We then use a component DidMount to run the function getQuestions.

//used to fetch the data from the APIcomponentDidMount(){this.getQuestions();}

Next, create in the src folder , a folder called ‘ components’ , followed by a file called QuestionBox.js.

In this file we will create a regular JS function for the function that will render the question text as well as a set of buttons to allow the user to select an answer.

import React, from “react”;const QuestionBox = ({question, options}) => {return (<div className=”questionBox”><div className=”question”>{question}</div></div>);};export default QuestionBox;

Then import this component into the index.js file and make changes so that your file is as follows :

import React, { Component } from "react";import ReactDOM from "react-dom";import "./assets/style.css";import quizService from './quizService';import QuestionBox from "./components/QuestionBox";class QuizBee extends Component {//state should always be located at nearest parent//Question bank will store the 5 questionsstate = {questionBank: []};getQuestions = () =>{quizService().then(question => {this.setState({questionBank: question});});};//used to fetch the data from the APIcomponentDidMount(){this.getQuestions();}render() {return (<div className="container"><div className="title">QuizBee</div>{this.state.questionBank.length > 0 &&this.state.questionBank.map(({question, answers, correct,questionId}) => <QuestionBox question={question} options={answers} key ={questionId}/>)}</div>);}}ReactDOM.render(<QuizBee />, document.getElementById("root"));

In the above file , one can see that we render instances of the question box components where we pass down two props namely :

questions and answers.

A property key is used as it is essential when rendering lists as it helps identify and correlate and instance of a component with the data it consumes.

Hooks API

We have used a simple JS function for the QuestionBox component which is generally used if we want a component for presentational purposes. However, we need to incorporate state and we will use a plug and play API known as Hooks.

Firstly, import the use state method, which allows us to use state in a functional component. Then we create a state variable called answer using the use state function and set the initial value from the options array that we get as a prop.

The set answer references to a function that can update the value of answer variable. Thereafter, we use map to render a series of buttons.

The value of the index from the answer array is used as the key attribute.

import React, {useState} from “react”;const QuestionBox = ({question, options}) => {const [answer, setAnswer] = useState(options);return (<div className=”questionBox”><div className=”question”>{question}</div>{answer.map((text, index) => (<buttonkey={index}className=”answerBtn”>{text}</button>))}</div>);};export default QuestionBox;

Next, the on click event listener will run a function. In the function we run the set answer method that was declared above using the use state hook, and we re write the set answer array with the new array that contains the chosen answer.

import React, {useState} from “react”;const QuestionBox = ({question, options}) => {const [answer, setAnswer] = useState(options);return (<div className=”questionBox”><div className=”question”>{question}</div>{answer.map((text, index) => (<buttonkey={index}className=”answerBtn”onClick={() => {setAnswer([text]);}}>{text}</button>))}</div>);};export default QuestionBox;

In your terminal, if you navigate to your projects directory and run npm start you should see the following in the page that pops up in your default browser:

We also want to compute the user response and maintain a score. This can be done in the QuizBee component but we need to pass the users response from the question box component to the QuizBee component. This can be done using props.

So in QuestionBox, we add a prop called selected and we add the following :

import React, {useState} from “react”;const QuestionBox = ({question, options, selected}) => {const [answer, setAnswer] = useState(options);return (<div className=”questionBox”><div className=”question”>{question}</div>{answer.map((text, index) => (<buttonkey={index}className=”answerBtn”onClick={() => {setAnswer([text]);selected(text);}}>{text}</button>))}</div>);};export default QuestionBox;

and in index.js:

import React, { Component } from “react”;import ReactDOM from “react-dom”;import “./assets/style.css”;import quizService from ‘./quizService’;class QuizBee extends Component {//state should always be located at nearest parent//Question bank will store the 5 questionsstate = {questionBank: [],score: 0,responses: 0};getQuestions = () =>{quizService().then(question => {this.setState({questionBank: question});});};computeAnswer = (answer, correctAnswer)=>{if (answer === correctAnswer){this.setState({score: this.state.score + 1});}this.setState({responses: this.state.responses < 5 ? this.state.responses + 1 : 5});}//used to fetch the data from the APIcomponentDidMount(){this.getQuestions();}render() {return (<div className=”container”><div className=”title”>QuizBee</div>{this.state.questionBank.length > 0 &&this.state.responses < 5 &&this.state.questionBank.map(({question, answers, correct,questionId}) => <QuestionBox question={question} options={answers} key ={questionId}selected={answer => this.computeAnswer(answer, correct)}/>)}</div>);}}ReactDOM.render(<QuizBee />, document.getElementById(“root”));

Next, we build another component to display the result and allow the user to play the game again. In the component folder, create another file called Results.js.

import React from “react”;const Result = ({score, playAgain}) => (<div className=”score-board”><div className=”score”>You scored {score} / 5 correct answers!</div><button className=”playBtn” onClick={playAgain}>Play again!</button></div>);export default Result;

Back in index js we add :

import React, { Component } from "react";import ReactDOM from "react-dom";import "./assets/style.css";import quizService from './quizService';class QuizBee extends Component {//state should always be located at nearest parent//Question bank will store the 5 questionsstate = {questionBank: [],score: 0,responses: 0};getQuestions = () =>{quizService().then(question => {this.setState({questionBank: question});});};computeAnswer = (answer, correctAnswer)=>{if (answer === correctAnswer){this.setState({score: this.state.score + 1});}this.setState({responses: this.state.responses < 5 ? this.state.responses + 1 : 5});}playAgain=()=> {this.getQuestions();this.setState({score:0,responses:0});}//used to fetch the data from the APIcomponentDidMount(){this.getQuestions();}render() {return (<div className="container"><div className="title">QuizBee</div>{this.state.questionBank.length > 0 &&this.state.responses < 5 &&this.state.questionBank.map(({question, answers, correct,questionId}) => <QuestionBox question={question} options={answers} key ={questionId}selected={answer => this.computeAnswer(answer, correct)}/>)}{this.state.responses ===5 ? (<Result score={this.state.score} playAgain={this.playAgain}/>): null}</div>);}}ReactDOM.render(<QuizBee />, document.getElementById("root"));

Now the app should be fully functional !

Thank you for reading! Feel free to make any other suggestions or recommendations for future challenges. Leave a few claps if you enjoyed it !

--

--

Daniel Xav De Oliveira

My aim is to document my journey as a Software Developer. Writing as I go along. To enforce new knowledge in my mind and to share with others !