Technical Blog Article — App 38: Interactive Quiz with React, TypeScript, Vite, and Fluent UI

The React roadmap defined for this project contains 100 progressive applications focused on internalizing the React mental model through repetition, architecture, and practical implementation. App 38 belongs to Block 2 — Interactivity and State, where the main objective is to deeply understand how React interfaces are driven entirely by state changes.

App 38 — Interactive Quiz — is one of the most important applications of the entire second block because it combines multiple React concepts together in a realistic user flow:

  • component state
  • conditional rendering
  • event handling
  • derived UI
  • form interaction
  • score calculation
  • list rendering
  • controlled components
  • component composition

At this point in the learning journey, React stops being only a “rendering library” and starts behaving like a true UI state engine.

The application visually looks simple:

  • show a question
  • select an answer
  • go to the next question
  • calculate the final score

But architecturally, this app introduces one of the most important ideas in React:

The UI is a function of state.

The user interface changes automatically because the internal state changes.

No manual DOM manipulation exists.
No imperative UI updates exist.
No document.querySelector() exists.
No manual show/hide logic exists.

Instead, React continuously re-renders the interface according to state.

This app is heavily connected to the official React Learn sections:

The application also continues using:

  • Vite
  • TypeScript
  • Fluent UI
  • component architecture
  • enterprise-style UI composition

following the architecture defined throughout the repository.


1. Creating the Project

The project starts with Vite.

mkdir bloco02
cd bloco02
npm create vite@latest app38-interactive-quiz -- --template react-ts

This command creates:

  • a React project
  • TypeScript configuration
  • Vite development environment
  • JSX/TSX support
  • npm scripts
  • development tooling

The react-ts template is extremely important because TypeScript becomes a core part of the architecture from the beginning.

After project creation:

cd app38-interactive-quiz
npm install

Now the dependencies are installed.

Then Fluent UI packages are added:

npm install @fluentui/react-components @fluentui/react-icons

Fluent UI provides:

  • enterprise UI components
  • accessibility support
  • Microsoft design consistency
  • keyboard navigation
  • responsive behavior
  • semantic controls

2. Creating the Folder Structure

mkdir src\components
mkdir src\data
mkdir src\models
mkdir src\styles

This structure reinforces the architectural separation introduced in earlier apps.

The final structure becomes:

src/
components/
data/
models/
styles/
App.tsx
main.tsx
index.css

Each folder has a clear responsibility.

FolderResponsibility
components/UI building blocks
data/Static quiz data
models/TypeScript contracts
styles/Global/project CSS

This separation is extremely important in enterprise React applications.


3. Creating the Files

New-Item artigo.md -ItemType File
New-Item src\models\QuizQuestion.ts -ItemType File
New-Item src\data\questions.ts -ItemType File
New-Item src\components\QuizCard.tsx -ItemType File
New-Item src\components\QuizResult.tsx -ItemType File

One of the important habits of this repository is creating architecture first before writing implementation.

This encourages thinking in:

  • responsibilities
  • composition
  • modularity
  • separation of concerns

instead of placing everything inside App.tsx.


4. Understanding the Quiz Model

File:

src/models/QuizQuestion.ts

Code:

export interface QuizQuestion {
id: number;
question: string;
options: string[];
correctAnswer: string;
}

This interface defines the structure of a quiz question.

This is extremely important because React applications scale better when data structures are explicitly modeled.

Each question must contain:

  • an id
  • the question text
  • possible answers
  • the correct answer

This provides:

  • type safety
  • autocomplete
  • predictable architecture
  • safer refactoring

Without TypeScript, a mistake like this could happen:

correctAnswer: 123

TypeScript prevents invalid data shapes.


5. Understanding the Data Layer

File:

src/data/questions.ts

This file contains the quiz questions.

The important concept here is:

UI derives from data.

The interface is not manually written question by question.

Instead:

  • the data describes the quiz
  • React renders the UI from the data

This is one of the most important React ideas.

The application does not care whether there are:

  • 4 questions
  • 40 questions
  • 400 questions

The rendering logic remains the same.


6. Why the Questions Are Stored Separately

A common beginner mistake is placing all data directly inside components.

Separating the data layer provides:

  • cleaner architecture
  • easier maintenance
  • future API integration
  • simpler testing
  • reusable datasets

Later, this file could easily be replaced by:

  • REST API data
  • database responses
  • GraphQL queries
  • SharePoint lists
  • Microsoft Graph responses

without rewriting the UI components.


7. Understanding QuizCard.tsx

This component is responsible for displaying:

  • the current question
  • possible answers
  • answer selection
  • next button

The component receives data through props.

This is extremely important.

React applications should follow:

Parent owns state
Child receives props
Child emits events

The props are:

interface QuizCardProps {
question: QuizQuestion;
selectedAnswer: string;
onSelectAnswer: (answer: string) => void;
onNextQuestion: () => void;
isLastQuestion: boolean;
}

This is classic React architecture.


8. Understanding Component Communication

The communication flow is:

App owns the state
QuizCard receives data
User interacts
QuizCard calls callback functions
App updates state
React re-renders UI

This is the core React rendering cycle.


9. Understanding RadioGroup

Inside the component:

<RadioGroup
value={selectedAnswer}
onChange={(_, data) => onSelectAnswer(data.value)}
>

This creates a controlled component.

The selected value is stored inside React state.

The UI does not own the state.
React owns the state.

This is one of the most important React ideas.


10. Controlled Components

This app reinforces the concept of controlled components introduced in earlier forms apps.

The selected answer is controlled by React:

value={selectedAnswer}

Whenever the user changes the selection:

onChange={(_, data) => onSelectAnswer(data.value)}

React updates state.

Then React re-renders the UI.

This creates a predictable data flow.


11. Rendering the Options

The quiz options are rendered dynamically:

{question.options.map((option) => (
<Radio
key={option}
value={option}
label={option}
/>
))}

This demonstrates declarative rendering.

Instead of manually creating:

  • Radio 1
  • Radio 2
  • Radio 3
  • Radio 4

React simply says:

For each option, render a Radio component.

12. Understanding map()

The map() function transforms arrays.

Conceptually:

array of data
array of UI elements

This is fundamental in React.

Almost every real React app uses:

  • map()
  • arrays
  • dynamic rendering

13. Understanding Stable Keys

key={option}

Keys help React identify elements during re-rendering.

This becomes critical when:

  • lists change
  • items are removed
  • items are reordered
  • items are updated

Without stable keys, React may:

  • re-render incorrectly
  • lose component state
  • produce warnings

14. Understanding the Next Button

<Button
appearance="primary"
disabled={!selectedAnswer}
>

This demonstrates derived UI.

The button becomes enabled only when:

  • the user selects an answer

The interface automatically reacts to state.

No manual DOM manipulation exists.


15. Understanding Derived UI

This line:

disabled={!selectedAnswer}

means:

If no answer exists,
disable the button.

This is declarative programming.

Instead of saying:

Find button
Disable button manually
Enable later manually

React derives the UI from state.


16. Understanding QuizResult.tsx

This component displays:

  • final score
  • percentage
  • restart button

It is only shown when:

isQuizFinished === true

Again, the UI derives from state.


17. Understanding Conditional Rendering

Inside App.tsx:

{isQuizFinished ? (
<QuizResult />
) : (
<QuizCard />
)}

This is one of the most important React concepts.

React dynamically changes the entire interface according to state.

When:

  • isQuizFinished = false
    → show questions

When:

  • isQuizFinished = true
    → show results

18. React Is NOT Imperative UI

This app clearly demonstrates that React is not:

show()
hide()
appendChild()
removeChild()

Instead:

State changes
React re-renders UI
UI automatically updates

This is the React mental model.


19. Understanding App.tsx

App.tsx owns all application state.

This is extremely important.

The parent component controls:

  • current question
  • selected answer
  • score
  • quiz completion state

This centralizes application behavior.


20. Understanding useState

The app uses multiple state variables:

const [currentQuestionIndex, setCurrentQuestionIndex]
const [selectedAnswer, setSelectedAnswer]
const [score, setScore]
const [isQuizFinished, setIsQuizFinished]

Each one stores a different part of the application memory.


21. Why React State Matters

React state is what allows the interface to evolve over time.

Without state:

  • the app would always display the same question
  • the score would never change
  • the UI would never update

State makes the interface dynamic.


22. Understanding Functional Updates

This line is extremely important:

setScore((previousScore) => previousScore + 1);

This is called a functional state update.

React Learn recommends this whenever:

  • the next state depends on the previous state

Why?

Because React batches updates internally.

Using the callback version guarantees correctness.


23. Understanding the Quiz Flow

The application flow is:

Start quiz
Display question
User selects answer
User clicks next
React validates answer
Update score
Move to next question
Repeat
Show final result

This is essentially a state machine.


24. Understanding Derived Variables

This line:

const currentQuestion =
questions[currentQuestionIndex];

creates derived data.

React Learn strongly recommends deriving values whenever possible instead of duplicating state.

The current question is derived from:

  • the question list
  • the current index

No duplicated state is necessary.


25. Understanding handleNextQuestion

This function contains the main business logic.

It:

  • validates the answer
  • updates score
  • checks last question
  • advances quiz
  • resets selected answer

This demonstrates how React event handlers control state transitions.


26. Understanding Quiz Completion

This logic:

if (isLastQuestion) {
setIsQuizFinished(true);
return;
}

changes the application mode.

The app moves from:

  • question mode

to:

  • result mode

through state only.


27. Understanding Restart Logic

function handleRestartQuiz() {
setCurrentQuestionIndex(0);
setSelectedAnswer("");
setScore(0);
setIsQuizFinished(false);
}

This resets the application back to the initial state.

Again:

  • no manual DOM reset exists
  • no imperative cleanup exists

React simply re-renders the UI according to the new state.


28. Understanding the Layout

The app uses:

display: "flex"
justifyContent: "center"
alignItems: "center"

This creates centered enterprise-style layout behavior.

The card is placed in the middle of the screen.

This style appears frequently in:

  • login pages
  • dashboards
  • onboarding flows
  • quizzes
  • setup wizards

29. Understanding Fluent UI in This App

This app uses several Fluent UI components:

ComponentPurpose
CardVisual container
RadioGroupControlled answer selection
RadioIndividual option
ButtonNavigation actions
BadgeFinal score display
Title1 / Title2Typography hierarchy
TextDescriptions

Fluent UI automatically provides:

  • spacing
  • accessibility
  • keyboard navigation
  • Microsoft visual identity
  • responsive behavior

30. Why This App Matters

This app is one of the first applications where React truly feels interactive.

It introduces:

  • dynamic UI
  • user-driven rendering
  • multi-state interfaces
  • state transitions
  • controlled components
  • event-driven rendering

Without understanding this app deeply, advanced React architecture becomes difficult later.

This app is the bridge between:

  • static UI
    and
  • real application behavior

Technical Summary

ConceptPurpose
useStateComponent memory
Controlled ComponentsReact-controlled inputs
RadioGroupAnswer selection
Conditional RenderingDynamic UI
Functional UpdatesSafe state changes
Derived StateAvoid duplicated data
PropsComponent communication
Event HandlingUser interaction
map()Dynamic rendering
Fluent UIEnterprise UI system
TypeScriptType safety
CompositionModular architecture

Official Documentation

React

Fluent UI

Vite

TypeScript


Current Project Progress

BlockAppNameStatus
Block 101Hello React FluentCompleted
Block 102Profile CardCompleted
Block 103Product ListCompleted
Block 104Microsoft Style User CardCompleted
Block 105Static DashboardCompleted
Block 106Corporate Sidebar MenuCompleted
Block 107Visual Task ListCompleted
Block 108Timeline EventsCompleted
Block 109Employee TableCompleted
Block 110Email ListCompleted
Block 111Grid of CardsCompleted
Block 112Image GalleryCompleted
Block 113Movie CatalogCompleted
Block 114Football TeamsCompleted
Block 115News PageCompleted
Block 116Financial DashboardCompleted
Block 117SharePoint Style LayoutCompleted
Block 118File ExplorerCompleted
Block 119Corporate PortalCompleted
Block 120Microsoft Landing PageCompleted
Block 221Modern CounterCompleted
Block 222Toggle ThemeCompleted
Block 223React CalculatorCompleted
Block 224Login FormCompleted
Block 225User RegistrationCompleted
Block 226ToDo ListCompleted
Block 227Shopping ListCompleted
Block 228Product FilterCompleted
Block 229Employee SearchCompleted
Block 230Shopping CartCompleted
Block 231Grade SimulatorCompleted
Block 232Inventory ControlCompleted
Block 233Contact AgendaCompleted
Block 234Currency ConverterCompleted
Block 235BMI CalculatorCompleted
Block 236Installment SimulatorCompleted
Block 237Voting PanelCompleted
Block 238Interactive QuizCurrent
Block 239Team ManagerNext

Edvaldo Guimrães Filho Avatar

Published by