npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-quiz-component

v1.1.1

Published

Customizable React quiz component for JSON-powered quizzes with scoring, timers, single or multiple choice answers, images, markdown, and callbacks.

Downloads

3,575

Readme

react-quiz-component

:orange_book: React Quiz Component

react-quiz-component is a ReactJS component that renders a quiz from a JSON object. It supports text and photo answers, single and multiple answer selection, scoring, timers, shuffling, progress display, custom locale text, and result callbacks.

NPM version License Total NPM Download

Features

  • JSON-based quiz source
  • Quiz landing page with title, synopsis, and number of questions
  • Input validation for quiz data
  • Text and photo answer choices
  • Single-answer and multiple-answer questions
  • Question markdown support
  • Optional question images
  • Per-question explanations and answer messages
  • Scoring with total and correct points
  • Question segments and selection tags
  • Question and answer shuffling
  • Instant feedback
  • Retry-until-correct mode
  • Reveal-answer-on-submit mode
  • Previous and next navigation
  • Default result page with all, correct, incorrect, and unanswered filters
  • Custom result page support
  • Quiz completion and per-question callbacks
  • Timer support with optional pause and resume
  • Optional progress bar

Installation

npm i react-quiz-component

Quick Start

import Quiz from 'react-quiz-component';

const quiz = {
  quizTitle: 'React Quiz Component Demo',
  quizSynopsis: 'A short quiz about React basics.',
  nrOfQuestions: 3,
  progressBarColor: '#9de1f6',
  questions: [
    {
      question: 'Which hook lets a function component store local state?',
      questionType: 'text',
      questionPic: 'https://dummyimage.com/600x240/9de1f6/000000&text=React+Hooks',
      answerSelectionType: 'single',
      answers: ['useMemo', 'useState', 'useEffect', 'useRef'],
      correctAnswer: '2',
      messageForCorrectAnswer: 'Correct. useState stores local component state.',
      messageForIncorrectAnswer: 'Not quite. Look for the hook that stores state.',
      explanation: 'useState returns a state value and a setter function.',
      point: 10,
      segment: 'React Hooks',
    },
    {
      question: 'Select the React rendering methods.',
      questionType: 'text',
      answerSelectionType: 'multiple',
      answers: ['createRoot', 'renderToString', 'setTimeout', 'querySelector'],
      correctAnswer: [1, 2],
      messageForCorrectAnswer: 'Correct. React supports client and server rendering APIs.',
      messageForIncorrectAnswer: 'Incorrect. Select only React rendering APIs.',
      explanation: 'createRoot is used for client rendering. renderToString is used for server rendering.',
      point: 20,
      segment: 'Rendering',
    },
    {
      question: 'Which image shows the React logo?',
      questionType: 'photo',
      answerSelectionType: 'single',
      answers: [
        'https://dummyimage.com/300x180/61dafb/000000&text=React',
        'https://dummyimage.com/300x180/f7df1e/000000&text=JS',
        'https://dummyimage.com/300x180/3178c6/ffffff&text=TS',
      ],
      correctAnswer: '1',
      messageForCorrectAnswer: 'Correct.',
      messageForIncorrectAnswer: 'Incorrect.',
      explanation: 'The React logo is commonly shown with a light blue atom-like mark.',
      point: 10,
      segment: 'Logos',
    },
  ],
};

export default function App() {
  return <Quiz quiz={quiz} />;
}

You can also import the quiz source from another file:

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

export default function App() {
  return <Quiz quiz={quiz} />;
}

Quiz Fields

| Name | Type | Required | Description | | :-- | :-- | :--: | :-- | | quizTitle | string | Y | Title shown on the landing page. | | quizSynopsis | string | N | Introductory text shown before the quiz starts. | | nrOfQuestions | number | N | Number of questions to use from questions. If omitted, all questions are used. | | questions | Question[] | Y | Question definitions. | | appLocale | Partial<AppLocale> | N | Locale text overrides. | | progressBarColor | string | N | Hex color used by the progress bar. Defaults to #9de1f6. |

Question Fields

| Name | Type | Required | Description | | :-- | :-- | :--: | :-- | | question | string | Y | Question text. Markdown is supported. | | questionType | 'text' \| 'photo' | Y | Use text for text answers or photo for image answer URLs. | | questionPic | string | N | Image URL displayed with the question. | | answerSelectionType | 'single' \| 'multiple' | Y | Whether the user selects one answer or multiple answers. | | answers | string[] | Y | Text answers or image URLs, depending on questionType. | | correctAnswer | string \| number[] | Y | Correct answer index or indexes. See answer indexing below. | | messageForCorrectAnswer | string | N | Message shown for a correct answer when instant feedback is enabled. | | messageForIncorrectAnswer | string | N | Message shown for an incorrect answer when instant feedback is enabled. | | explanation | string | N | Explanation shown after answering and on the result page. | | point | string \| number | N | Points assigned to the question. | | segment | string | N | Label shown with the question tags. |

Answer Indexing

Answer indexes are 1-based.

For a single-answer question, correctAnswer is a string:

{
  answerSelectionType: 'single',
  answers: ['First', 'Second', 'Third'],
  correctAnswer: '2',
}

For a multiple-answer question, correctAnswer is an array of numbers:

{
  answerSelectionType: 'multiple',
  answers: ['First', 'Second', 'Third'],
  correctAnswer: [1, 3],
}

Examples

Shuffle Questions

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

<Quiz quiz={quiz} shuffle />;

Shuffle Answers

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

<Quiz quiz={quiz} shuffleAnswer />;

Instant Feedback

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

<Quiz quiz={quiz} showInstantFeedback />;

Retry Until Correct

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

<Quiz quiz={quiz} continueTillCorrect />;

Reveal Answer On Submit

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

<Quiz quiz={quiz} revealAnswerOnSubmit />;

Previous And Next Navigation

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

<Quiz quiz={quiz} allowNavigation />;

Timer

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

<Quiz quiz={quiz} timer={60} />;

Pause And Resume Timer

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

<Quiz quiz={quiz} timer={60} allowPauseTimer />;

Progress Bar

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

const quizWithProgressColor = {
  ...quiz,
  progressBarColor: '#34d399',
};

<Quiz quiz={quizWithProgressColor} enableProgressBar />;

Disable Landing Synopsis

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

<Quiz quiz={quiz} disableSynopsis />;

Completion Callback

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

const handleComplete = (summary) => {
  console.log(summary);
};

<Quiz quiz={quiz} onComplete={handleComplete} />;

Question Submit Callback

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

const handleQuestionSubmit = ({ question, userAnswer, isCorrect }) => {
  console.log(question, userAnswer, isCorrect);
};

<Quiz quiz={quiz} onQuestionSubmit={handleQuestionSubmit} />;

Custom Result Page

Set showDefaultResult to false when using customResultPage.

import Quiz from 'react-quiz-component';
import { quiz } from './quiz';

const renderCustomResultPage = (summary) => {
  return (
    <div>
      <h2>Custom result page</h2>
      <p>
        You scored {summary.correctPoints} out of {summary.totalPoints}.
      </p>
    </div>
  );
};

<Quiz
  quiz={quiz}
  showDefaultResult={false}
  customResultPage={renderCustomResultPage}
/>;

Props

| Name | Type | Default | Required | Description | | :-- | :-- | :-- | :--: | :-- | | quiz | Quiz | null | Y | Quiz source object. | | shuffle | boolean | false | N | Shuffle questions before rendering. | | shuffleAnswer | boolean | false | N | Shuffle answer choices before rendering. | | showDefaultResult | boolean | true | N | Show the built-in result page when the quiz ends. | | onComplete | (summary: QuestionSummary) => void | undefined | N | Called once when the quiz completes. | | customResultPage | (summary: QuestionSummary) => React.ReactElement | undefined | N | Render a custom result page. Use with showDefaultResult={false}. | | showInstantFeedback | boolean | false | N | Show correct or incorrect messages after answers are submitted. | | continueTillCorrect | boolean | false | N | For single-answer questions, let the user keep trying until the correct answer is selected. | | revealAnswerOnSubmit | boolean | false | N | Let the user select an answer before submitting and revealing correctness. | | allowNavigation | boolean | false | N | Show previous and next controls so users can move between questions. | | onQuestionSubmit | (data: QuestionSubmitData) => void | undefined | N | Called when a question answer is submitted with the question, user answer, and correctness. | | disableSynopsis | boolean | false | N | Skip the landing page and start the quiz immediately. | | timer | number | undefined | N | Quiz duration in seconds. Must be greater than 0. | | allowPauseTimer | boolean | false | N | Allow pausing and resuming when timer is set. | | enableProgressBar | boolean | false | N | Show a progress bar above the quiz. |

Locale Customization

Add appLocale to the quiz source to override any default text. Placeholders such as <questionLength>, <correctIndexLength>, <correctPoints>, <totalPoints>, <numberOfSelection>, and <marks> are replaced dynamically.

const quiz = {
  quizTitle: 'React Quiz Component Demo',
  questions: [],
  appLocale: {
    landingHeaderText: '<questionLength> Questions',
    question: 'Question',
    startQuizBtn: 'Start Quiz',
    resultFilterAll: 'All',
    resultFilterCorrect: 'Correct',
    resultFilterIncorrect: 'Incorrect',
    resultFilterUnanswered: 'Unanswered',
    nextQuestionBtn: 'Next',
    prevQuestionBtn: 'Prev',
    resultPageHeaderText: 'You have completed the quiz. You got <correctIndexLength> out of <questionLength> questions.',
    resultPagePoint: 'You scored <correctPoints> out of <totalPoints>.',
    pauseScreenDisplay: 'Test is paused. Clicked the Resume button to continue',
    timerTimeRemaining: 'Time Remaining',
    timerTimeTaken: 'Time Taken',
    pauseScreenPause: 'Pause',
    pauseScreenResume: 'Resume',
    singleSelectionTagText: 'Single Selection',
    multipleSelectionTagText: 'Multiple Selection',
    pickNumberOfSelection: 'Pick <numberOfSelection>',
    marksOfQuestion: '(<marks> marks)',
  },
};

Callback Payloads

onComplete(summary) and customResultPage(summary) receive a QuestionSummary object:

type QuestionSummary = {
  numberOfQuestions: number;
  numberOfCorrectAnswers: number;
  numberOfIncorrectAnswers: number;
  questions: Question[];
  userInput: (number | number[] | undefined)[];
  totalPoints: number;
  correctPoints: number;
  timeTaken: number;
};

onQuestionSubmit(data) receives the submitted question result:

type QuestionSubmitData = {
  question: Question;
  userAnswer: number | number[] | undefined;
  isCorrect: boolean;
};

For userInput and userAnswer, single-answer questions use a 1-based number such as 2, multiple-answer questions use a 1-based number array such as [1, 3], and unanswered questions can be undefined.

Development And Contribution

  • Clone the repository
  • Run npm install
  • Run npm run dev
  • Run npm run lint
  • Make a PR to develop and describe the changes

Demo

The demo is available at https://wingkwong.github.io/react-quiz-component/

License

This project is licensed under the MIT License - see the LICENSE file for details