DEV Community

Tamilselvan K
Tamilselvan K

Posted on

Day-54 Building a Simple React Quiz App Using Context API

In this post, I’ll walk through how I created a basic quiz application using React. The goal of this app is to let users enter their name, take a multiple-choice quiz, and see their result at the end. I used React hooks and the Context API to manage global state like username, score, and gamestate.


Folder Structure

src/
├── App.js
├── App.css
├── assets/
│   └── questions.json
├── components/
│   ├── User.js
│   ├── Quiz.js
│   └── Result.js
Enter fullscreen mode Exit fullscreen mode

App.js

import logo from './logo.svg';
import './App.css';
import User from './components/User';
import Quiz from './components/Quiz';
import Result from './components/Result';
import { createContext, useEffect, useState } from 'react';

export const quizContext = createContext();

function App() {
  const [gamestate, setGamestate] = useState("users");
  const [username, setUsername] = useState("");
  const [score, setScore] = useState(0);

  return (
    <div className="App">
      <header className="App-header">
        <quizContext.Provider value={{ gamestate, setGamestate, username, setUsername, score, setScore }}>
          {gamestate === 'users' && <User />}
          {gamestate === 'playing' && <Quiz />}
          {gamestate === 'result' && <Result />}
        </quizContext.Provider>
      </header>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

User.js

import React, { useContext, useEffect, useRef } from 'react';
import { quizContext } from '../App';

function User() {
  const { gamestate, setGamestate, username, setUsername } = useContext(quizContext);
  const userRef = useRef();

  useEffect(() => {
    userRef.current.focus();
  }, []);

  function startPlaying() {
    setUsername(userRef.current.value);
    setGamestate("playing");
  }

  return (
    <div>
      <input type="text" placeholder='Enter useName' ref={userRef} />
      <button onClick={startPlaying}>Start Quiz</button>
    </div>
  );
}

export default User;
Enter fullscreen mode Exit fullscreen mode

Quiz.js

import React, { useContext, useState } from 'react';
import questions from '../assets/questions.json';
import { quizContext } from '../App';

function Quiz() {
  const [currentQuestion, setCurrentQuestion] = useState(0);
  const [optionChosen, setOptionChosen] = useState("");
  const { setGamestate, score, setScore } = useContext(quizContext);

  function next() {
    if (optionChosen === questions[currentQuestion]['answer']) {
      setScore(score + 1);
    }
    setCurrentQuestion(currentQuestion + 1);
    setOptionChosen("");
  }

  function finish() {
    if (optionChosen === questions[currentQuestion]['answer']) {
      setScore(score + 1);
    }
    setGamestate("result");
  }

  return (
    <div>
      {questions[currentQuestion]['prompt']}
      {
        ['A', 'B', 'C', 'D'].map((opt) => (
          <button onClick={() => setOptionChosen(`option${opt}`)}>
            {questions[currentQuestion][`option${opt}`]}
          </button>
        ))
      }
      {
        (questions.length - 1 === currentQuestion)
          ? (<button onClick={finish}>Finish</button>)
          : (<button onClick={next}>Next</button>)
      }
    </div>
  );
}

export default Quiz;
Enter fullscreen mode Exit fullscreen mode

Result.js

import React, { useContext } from 'react';
import { quizContext } from '../App';
import questions from '../assets/questions.json';

function Result() {
  const { setGamestate, setUsername, score, username, setScore } = useContext(quizContext);

  function restartQuiz() {
    setUsername("");
    setScore(0);
    setGamestate("users");
  }

  return (
    <div>
      <h1>{`${username} scored ${score} out of ${questions.length}`}</h1>
      <button onClick={restartQuiz}>Restart Quiz</button>
    </div>
  );
}

export default Result;
Enter fullscreen mode Exit fullscreen mode

questions.json

[
  {
    "prompt": "HTML stands for?",
    "optionA": "HyperText Markup Language",
    "optionB": "HyperText Mark Language",
    "optionC": "HyperText Markup Learn",
    "optionD": "Hyper Markup Language",
    "answer": "optionA"
  },
  {
    "prompt": "JS stands for?",
    "optionA": "HyperText Markup Language",
    "optionB": "CSS",
    "optionC": "TypeScript",
    "optionD": "JavaScript",
    "answer": "optionD"
  },
  {
    "prompt": "CSS stands for?",
    "optionA": "Cascading Style Sheets",
    "optionB": "Cascading Sheet Styles",
    "optionC": "Colorful Style Sheets",
    "optionD": "Computer Style Sheets",
    "answer": "optionA"
  },
  {
    "prompt": "Which HTML element is used for the largest heading?",
    "optionA": "<h1>",
    "optionB": "<h2>",
    "optionC": "<h3>",
    "optionD": "<h4>",
    "answer": "optionA"
  },
  {
    "prompt": "Which symbol is used to select classes in CSS?",
    "optionA": "#",
    "optionB": ".",
    "optionC": "*",
    "optionD": "&",
    "answer": "optionB"
  }
]
Enter fullscreen mode Exit fullscreen mode

What I Learned

  • Using useRef for managing input focus
  • Conditional rendering based on state
  • Managing global state using Context API
  • Handling multiple components that rely on shared state
  • Loading data dynamically from a JSON file

Top comments (0)