As React applications grow, components often need access to the same information. Passing data through multiple component levels using props can quickly become difficult to maintain. This problem is commonly known as prop drilling.

App 71 — Favorites System with React Context API, TypeScript, Fluent UI, and Vite

Introduction

As React applications grow, components often need access to the same information. Passing data through multiple component levels using props can quickly become difficult to maintain. This problem is commonly known as prop drilling.

React provides a built-in solution called Context API, which allows data to be shared globally across a component tree without manually passing props through every intermediate component.

In App 71 — Favorites System, we build a complete favorites management feature using React Context API, TypeScript, Fluent UI, and Vite. Users can mark products as favorites, remove favorites, and instantly see updates reflected across the application.

This project continues the architecture concepts introduced in App 70 and demonstrates one of the most important enterprise React patterns: centralized shared state.

The application follows the official React philosophy:

  • UI is derived from state
  • Components remain reusable
  • State is centralized when appropriate
  • Context distributes data efficiently
  • Rendering remains declarative

Official React documentation recommends Context when multiple components need access to the same data across the application hierarchy.


Project Objectives

The main goals of this application are:

  • Learn React Context API
  • Build a global state provider
  • Create reusable custom hooks
  • Share data between unrelated components
  • Implement a Favorites feature
  • Use Fluent UI enterprise components
  • Practice immutable state updates
  • Understand centralized state architecture

By the end of this project you will understand how enterprise React applications manage shared information without excessive prop passing.


Why Context API Matters

Imagine a large application:

App
├── Header
├── Sidebar
├── Dashboard
│ ├── Product List
│ ├── Product Details
│ └── Analytics
└── Footer

If favorites are needed in:

  • Product List
  • Product Details
  • Header Counter
  • Sidebar Summary

Passing props through every layer becomes cumbersome.

Instead:

FavoritesProvider
Shared Global State
┌──────┼──────┐
▼ ▼ ▼
Header Product Sidebar

Every component can directly access the favorites data.

This is exactly what Context API was designed for.


Understanding the Architecture

This application uses the following architecture:

src/
├── components/
│ ├── ProductCard.tsx
│ ├── ProductList.tsx
│ └── FavoritesPanel.tsx
├── context/
│ └── FavoritesContext.tsx
├── data/
│ └── products.ts
├── models/
│ └── Product.ts
├── App.tsx
├── main.tsx
└── index.css

Each layer has a single responsibility.


The Product Model

The Product interface defines the structure of every product:

export interface Product {
id: number;
name: string;
category: string;
}

Benefits:

  • Type safety
  • Better IntelliSense
  • Compile-time validation
  • Easier maintenance

Strong typing becomes increasingly important as applications grow.


Static Product Data

The application uses mock data:

export const products: Product[] = [...]

In future applications this data could come from:

  • REST APIs
  • GraphQL
  • Azure Functions
  • SharePoint Lists
  • SQL databases

For learning purposes, static data keeps the focus on Context architecture.


Building the Favorites Context

The heart of the application is:

createContext<FavoritesContextType | null>(null);

The Context acts as a global container.

It stores:

  • favorites
  • addFavorite()
  • removeFavorite()

Every component inside the provider can access this information.


Creating the Provider

The provider wraps the application:

<FavoritesProvider>
<App />
</FavoritesProvider>

Think of the provider as a global storage area.

Every child component gains access to:

favorites
addFavorite()
removeFavorite()

without prop drilling.


Understanding React State

The favorites collection is stored using:

const [favorites, setFavorites] =
useState<Product[]>([]);

This state becomes the single source of truth.

Important React principle:

One source of truth

Instead of storing favorites in multiple places, everything comes from one centralized state object.


Adding Favorites

The addFavorite function:

function addFavorite(product: Product)

prevents duplicate entries:

const exists =
favorites.some(
item => item.id === product.id
);

If the product already exists, React does not add it again.

This demonstrates business rule enforcement inside state logic.


Removing Favorites

The remove function uses immutable updates:

setFavorites(
favorites.filter(
item => item.id !== id
)
);

React strongly encourages immutable state updates.

Why?

Because immutable updates:

  • simplify debugging
  • improve predictability
  • work naturally with React rendering

Custom Hook Pattern

Instead of repeatedly writing:

useContext(FavoritesContext)

the application exposes:

useFavorites()

This is a custom hook.

Benefits:

  • cleaner code
  • centralized logic
  • easier refactoring
  • reusable abstraction

This pattern is heavily used in enterprise React projects.


ProductCard Component

Each product is displayed inside a Fluent UI Card.

Responsibilities:

  • display product information
  • provide favorite action
  • communicate with Context

The component does not own favorites state.

Instead:

User clicks button
Context updates
React re-renders
All consumers update automatically

This separation improves maintainability.


ProductList Component

ProductList demonstrates declarative rendering:

products.map(...)

React converts data into UI.

Instead of manually creating cards:

Create card
Append card
Create card
Append card

we simply describe:

Render one card for each product

React handles the DOM updates.


FavoritesPanel Component

The FavoritesPanel consumes Context.

It displays:

  • favorite items
  • favorite count
  • remove actions

The counter:

favorites.length

is derived state.

React best practice:

Do not store values that can be calculated.

Instead of:

const [count, setCount]

calculate:

favorites.length

This eliminates synchronization problems.


Fluent UI Integration

The application uses Fluent UI for enterprise styling.

Main components:

  • Card
  • Button
  • Text
  • Title

Advantages:

  • Accessibility
  • Consistent spacing
  • Microsoft design language
  • Keyboard navigation
  • Enterprise appearance

This aligns the project with Microsoft ecosystem development standards.


Why This Is Enterprise Architecture

Many real-world systems require shared state:

Examples:

  • Shopping cart
  • Notifications
  • Authentication
  • User profile
  • Theme settings
  • Favorites
  • Language settings

Context API provides a lightweight solution before moving into more advanced state libraries.


React Mental Model

The most important lesson:

Favorites are state.
UI derives from state.
React renders the result.

The developer never manipulates the DOM directly.

Instead:

State changes
React re-renders
UI updates automatically

This is the essence of React.


Technical Summary

ConceptPurpose
Context APIGlobal state sharing
Provider PatternDistributes shared state
useContextAccess shared data
Custom HookSimplifies Context access
useStateStores favorites
Fluent UIEnterprise UI
Immutable UpdatesSafe state changes
Derived StateFavorites count
TypeScriptType safety
Component CompositionReusable architecture

Official Documentation

React

Fluent UI

Vite

TypeScript


Final Thoughts

App 71 introduces one of the most important architectural concepts in React: shared state through Context.

While the Favorites feature appears simple, the underlying architecture is used in many enterprise applications.

Mastering Context API prepares you for:

  • Authentication systems
  • Global notifications
  • User preferences
  • Theme management
  • Enterprise dashboards
  • SharePoint-style applications
  • Complex React architectures

The key takeaway is:

Shared data
→ Context API
→ React rendering
→ Consistent UI

This pattern becomes a foundation for scalable React development.

Create the article file

New-Item artigo.md -ItemType File

Current Progress

BlockAppNameStatus
Block 468Data CacheCompleted
Block 469Custom Fetch HookCompleted
Block 470Global Context ControlCompleted
Block 471Favorites SystemCurrent
Block 472API DataGridNext
Block 473Analytics DashboardUpcoming
Block 474Cryptocurrency MonitorUpcoming
Block 475Repository ExplorerUpcoming

Current App: 71 — Favorites System
Next App: 72 — API DataGrid

Edvaldo Guimrães Filho Avatar

Published by