Quiz on React

React Quiz App with 3 Screens using JSON & Fetch

🧠 Build a 3-Screen React Quiz App with JSON & Fetch

This tutorial shows how to build a React Quiz App with 3 screens and data coming from JSON files hosted on GitHub Pages. We'll use fetch to load data dynamically and React Router to handle screen transitions.

Code on Github

Live on Github Pages

🧱 App Structure

  1. Screen 1: List of Subjects
  2. Screen 2: List of Quizzes in Selected Subject
  3. Screen 3: Quiz Viewer
---

📁 JSON Data Example

subjects.json

[
  {
    "subjectNo": 1,
    "subjectName": "JavaScript",
    "quizListUrl": "https://yourusername.github.io/data/js-quizzes.json"
  },
  {
    "subjectNo": 2,
    "subjectName": "Python",
    "quizListUrl": "https://yourusername.github.io/data/python-quizzes.json"
  }
]

js-quizzes.json

[
  {
    "quizNo": 1,
    "quizName": "JS Basics",
    "quizUrl": "https://yourusername.github.io/data/js-basics-quiz.json"
  }
]

js-basics-quiz.json

[
  {
    "question": "What does JS stand for?",
    "options": ["JavaScript", "JustScript", "JScript", "Java"],
    "answer": "JavaScript"
  }
]
---

🚀 Project Setup

npx create-react-app react-quiz-app
cd react-quiz-app
npm install react-router-dom
---

📂 File: App.js

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import SubjectList from './SubjectList';
import QuizList from './QuizList';
import QuizScreen from './QuizScreen';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<SubjectList />} />
        <Route path="/quizzes" element={<QuizList />} />
        <Route path="/quiz" element={<QuizScreen />} />
      </Routes>
    </Router>
  );
}

export default App;
---

📂 File: SubjectList.js

import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';

function SubjectList() {
  const [subjects, setSubjects] = useState([]);
  const navigate = useNavigate();

  useEffect(() => {
    fetch('https://yourusername.github.io/data/subjects.json')
      .then(res => res.json())
      .then(data => setSubjects(data));
  }, []);

  const handleClick = (quizListUrl) => {
    localStorage.setItem('quizListUrl', quizListUrl);
    navigate('/quizzes');
  };

  return (
    <div>
      <h2>Select Subject</h2>
      {subjects.map(sub => (
        <button key={sub.subjectNo} onClick={() => handleClick(sub.quizListUrl)}>
          {sub.subjectName}
        </button>
      ))}
    </div>
  );
}

export default SubjectList;
---

📂 File: QuizList.js

import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';

function QuizList() {
  const [quizzes, setQuizzes] = useState([]);
  const navigate = useNavigate();

  useEffect(() => {
    const url = localStorage.getItem('quizListUrl');
    fetch(url)
      .then(res => res.json())
      .then(data => setQuizzes(data));
  }, []);

  const handleQuizClick = (quizUrl) => {
    localStorage.setItem('quizUrl', quizUrl);
    navigate('/quiz');
  };

  return (
    <div>
      <h2>Select Quiz</h2>
      {quizzes.map(q => (
        <button key={q.quizNo} onClick={() => handleQuizClick(q.quizUrl)}>
          {q.quizName}
        </button>
      ))}
    </div>
  );
}

export default QuizList;
---

📂 File: QuizScreen.js

import { useEffect, useState } from 'react';

function QuizScreen() {
  const [questions, setQuestions] = useState([]);
  const [index, setIndex] = useState(0);
  const [score, setScore] = useState(0);
  const [showResult, setShowResult] = useState(false);

  useEffect(() => {
    const url = localStorage.getItem('quizUrl');
    fetch(url)
      .then(res => res.json())
      .then(data => setQuestions(data));
  }, []);

  const handleOptionClick = (option) => {
    if (option === questions[index].answer) setScore(score + 1);

    const next = index + 1;
    if (next < questions.length) {
      setIndex(next);
    } else {
      setShowResult(true);
    }
  };

  if (!questions.length) return <p>Loading...</p>;

  if (showResult) return <h2>Your Score: {score}/{questions.length}</h2>;

  const q = questions[index];

  return (
    <div>
      <h3>Q{index + 1}: {q.question}</h3>
      {q.options.map((opt, i) => (
        <button key={i} onClick={() => handleOptionClick(opt)}>{opt}</button>
      ))}
    </div>
  );
}

export default QuizScreen;
---

📦 Deployment Tips

- Host JSON files in your GitHub repository under `docs/data/` - Use GitHub Pages to serve them. - Replace all `yourusername.github.io` links with your actual username/repo path. ---

💡 Conclusion

This 3-screen quiz app demonstrates how to dynamically load data from external sources and navigate using React Router. You can extend it by adding: - Timer - Category filters - User authentication - Leaderboard --- Want a downloadable ZIP or deploy link for GitHub Pages? Just let me know!

Post a Comment

0 Comments

Me