Flowchart showing React app components, state management, API calls, and GitHub API endpoints

Technical Blog Article — App 64: GitHub User Explorer with React, TypeScript, Vite, and Fluent UI

Introduction

Modern React applications rarely operate using only static local data. Real enterprise systems constantly synchronize with external services such as APIs, databases, authentication providers, analytics systems, CRMs, ERPs, and cloud platforms. Because of this, understanding asynchronous rendering and external synchronization is one of the most important transitions in React learning.

User types username
→ React updates input state

User clicks Search
→ searchUsername updates

Dependency array changes
→ useEffect executes

GitHub API request runs
→ loading state becomes true

Data arrives
→ user state updates

React re-renders
→ GitHubProfileCard appears

  • useEffect
  • external synchronization
  • async rendering
  • REST APIs
  • loading states
  • error handling
  • service architecture
  • professional state organization

According to the ReactLab roadmap, App 64 is focused on GitHub API integration and React Effects architecture.

This app introduces one of the most important React mental models:

UI reacts to state.
State reacts to async data.
Effects synchronize React with external systems.

This is fundamentally different from beginner JavaScript applications that manually manipulate HTML.

Instead of:

find HTML element
change DOM manually
inject content manually

React applications follow:

event
→ state update
→ effect runs
→ async request
→ state changes
→ React re-renders UI

This app follows the official React architecture guidance from:


What This App Builds

The application allows users to:

  • type a GitHub username
  • execute an API request
  • load GitHub profile data
  • display the profile visually
  • handle loading state
  • handle API failures
  • render enterprise-style UI with Fluent UI

The final UI displays:

  • GitHub avatar
  • profile name
  • biography
  • repository count
  • followers
  • following
  • direct GitHub profile link

The application demonstrates the complete lifecycle of asynchronous React rendering.


Main Concepts Introduced

ConceptPurpose
useEffectSynchronize with external systems
fetch()Execute HTTP requests
async/awaitHandle asynchronous operations
loading stateRepresent pending requests
error stateRepresent failures
conditional renderingRender different UI states
TypeScript interfacesType API responses
service layerSeparate API logic
controlled inputReact-controlled form input
Fluent UI CardsEnterprise presentation layer

Create the Project

Create the application

mkdir bloco04
cd bloco04
npm create vite@latest app64-github-user-explorer -- --template react-ts
cd app64-github-user-explorer

Install dependencies:

npm install

Install Fluent UI:

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

Create the Folder Structure

New-Item src\components -ItemType Directory
New-Item src\models -ItemType Directory
New-Item src\services -ItemType Directory
New-Item src\styles -ItemType Directory

Create files:

New-Item src\models\GitHubUser.ts -ItemType File
New-Item src\services\githubService.ts -ItemType File
New-Item src\components\SearchBar.tsx -ItemType File
New-Item src\components\GitHubProfileCard.tsx -ItemType File
New-Item artigo.md -ItemType File

Final Project Structure

app64-github-user-explorer/
src/
components/
GitHubProfileCard.tsx
SearchBar.tsx
models/
GitHubUser.ts
services/
githubService.ts
styles/
App.tsx
main.tsx
index.css

This architecture is important because React applications should separate responsibilities clearly.

LayerResponsibility
ComponentsUI rendering
ModelsTypeScript contracts
ServicesAPI communication
AppState orchestration
main.tsxReact root mounting

Create the GitHub Model

src\models\GitHubUser.ts

export interface GitHubUser {
login: string;
avatar_url: string;
name: string;
bio: string;
public_repos: number;
followers: number;
following: number;
html_url: string;
}

This interface defines the exact structure expected from GitHub’s API.

This is extremely important because APIs are external systems. Strong typing makes React applications safer and more maintainable.

Without TypeScript interfaces:

  • data becomes unpredictable
  • refactoring becomes dangerous
  • rendering bugs become easier to introduce

Understanding API Contracts

The interface acts as a contract between:

  • your frontend
  • the GitHub API

Conceptually:

GitHub API
→ returns JSON
TypeScript Interface
→ defines expected structure
React Components
→ safely render data

This is the foundation of enterprise frontend engineering.


Create the GitHub Service

src\services\githubService.ts

import type { GitHubUser } from "../models/GitHubUser";
export async function fetchGitHubUser(
username: string
): Promise<GitHubUser> {
const response = await fetch(
`https://api.github.com/users/${username}`
);
if (!response.ok) {
throw new Error("GitHub user not found.");
}
return response.json();
}

Why a Service Layer Matters

One of the biggest architectural improvements in modern React apps is separating API logic from UI rendering.

Bad approach:

Component
contains:
- UI
- API requests
- parsing
- business logic

Better approach:

Service layer
handles APIs
Components
focus on rendering

Benefits:

  • reusable services
  • easier testing
  • cleaner components
  • scalable architecture

Understanding fetch()

await fetch(...)

This performs an HTTP request to GitHub’s servers.

Flow:

React app
→ sends HTTP request
→ GitHub API responds
→ JSON data arrives
→ React updates state
→ UI re-renders

This is the first real external synchronization pattern introduced in the ReactLab roadmap.


Understanding async/await

Without asynchronous behavior:

The browser would freeze waiting for data.

Instead:

Request runs asynchronously.
React keeps rendering.
When data arrives:
state updates
UI updates

This is critical in modern frontend engineering.


Create the Search Bar Component

src\components\SearchBar.tsx

import {
Button,
Input,
} from "@fluentui/react-components";
interface SearchBarProps {
username: string;
onUsernameChange: (value: string) => void;
onSearch: () => void;
}
export function SearchBar({
username,
onUsernameChange,
onSearch,
}: SearchBarProps) {
return (
<div
style={{
display: "flex",
gap: "12px",
}}
>
<Input
placeholder="Enter GitHub username"
value={username}
onChange={(_, data) =>
onUsernameChange(data.value)
}
/>
<Button
appearance="primary"
onClick={onSearch}
>
Search
</Button>
</div>
);
}

Controlled Inputs in React

The input uses:

value={username}

combined with:

onChange={...}

This creates a controlled input.

The React mental model is:

React state controls the UI.

Not:

Browser DOM controls the UI.

This is one of the most important React architecture principles.


Create the GitHub Profile Card

src\components\GitHubProfileCard.tsx

import {
Avatar,
Card,
Link,
Text,
Title2,
} from "@fluentui/react-components";
import type { GitHubUser } from "../models/GitHubUser";
interface GitHubProfileCardProps {
user: GitHubUser;
}
export function GitHubProfileCard({
user,
}: GitHubProfileCardProps) {
return (
<Card
style={{
padding: "24px",
marginTop: "24px",
display: "flex",
flexDirection: "column",
gap: "16px",
}}
>
<Avatar
image={{
src: user.avatar_url,
}}
size={96}
/>
<Title2>
{user.name || user.login}
</Title2>
<Text>{user.bio}</Text>
<Text>
Public Repositories: {user.public_repos}
</Text>
<Text>
Followers: {user.followers}
</Text>
<Text>
Following: {user.following}
</Text>
<Link
href={user.html_url}
target="_blank"
>
Open GitHub Profile
</Link>
</Card>
);
}

Why This Component Is Important

This component is intentionally pure.

It:

  • receives props
  • returns JSX
  • does not own state
  • does not fetch APIs

This separation is critical in React architecture.


Create App.tsx

src\App.tsx

import { useEffect, useState } from "react";
import {
Spinner,
Text,
Title1,
} from "@fluentui/react-components";
import { SearchBar } from "./components/SearchBar";
import { GitHubProfileCard } from "./components/GitHubProfileCard";
import type { GitHubUser } from "./models/GitHubUser";
import { fetchGitHubUser } from "./services/githubService";
function App() {
const [username, setUsername] =
useState("microsoft");
const [searchUsername, setSearchUsername] =
useState("microsoft");
const [user, setUser] =
useState<GitHubUser | null>(null);
const [loading, setLoading] =
useState(false);
const [error, setError] =
useState("");
useEffect(() => {
async function loadUser() {
try {
setLoading(true);
setError("");
const data =
await fetchGitHubUser(searchUsername);
setUser(data);
} catch (err) {
setError(
"Unable to load GitHub profile."
);
setUser(null);
} finally {
setLoading(false);
}
}
loadUser();
}, [searchUsername]);
return (
<main
style={{
minHeight: "100vh",
backgroundColor: "#f5f5f5",
padding: "48px",
boxSizing: "border-box",
}}
>
<section
style={{
maxWidth: "700px",
margin: "0 auto",
}}
>
<Title1>
GitHub User Explorer
</Title1>
<Text>
Search GitHub users using React,
TypeScript, Fluent UI, and Effects.
</Text>
<div
style={{
marginTop: "24px",
}}
>
<SearchBar
username={username}
onUsernameChange={setUsername}
onSearch={() =>
setSearchUsername(username)
}
/>
</div>
{loading && (
<div
style={{
marginTop: "24px",
}}
>
<Spinner label="Loading profile..." />
</div>
)}
{error && (
<Text
style={{
color: "red",
marginTop: "24px",
display: "block",
}}
>
{error}
</Text>
)}
{user && !loading && (
<GitHubProfileCard user={user} />
)}
</section>
</main>
);
}
export default App;

Understanding useEffect

This is the core architectural concept:

useEffect(() => {
...
}, [searchUsername]);

The effect synchronizes React with GitHub’s API.

Official React definition:

Effects synchronize your components with external systems.

Synchronizing with Effects


Understanding the Dependency Array

[searchUsername]

This means:

Run the effect whenever searchUsername changes.

This is one of the most important parts of Effect architecture.


Why We Use Two Username States

username
searchUsername

This is intentional.

StatePurpose
usernameCurrent typing
searchUsernameConfirmed search

Without this separation:

  • every keystroke would trigger an API request

This is an enterprise optimization pattern.


Loading State

const [loading, setLoading] =
useState(false);

Asynchronous rendering always requires:

  • pending state
  • success state
  • failure state

Professional UIs never assume requests are instant.


Error State

const [error, setError] =
useState("");

Real systems fail.

Possible failures:

  • invalid usernames
  • rate limits
  • internet failures
  • server downtime

Professional React applications must represent failures gracefully.


Conditional Rendering

{loading && <Spinner />}
{error && <Text>{error}</Text>}
{user && !loading && (
<GitHubProfileCard user={user} />
)}

This is declarative UI architecture.

The UI changes according to state.


Why This App Is Architecturally Important

This app introduces:

React State
→ Effects
→ API Integration
→ Async Rendering
→ Enterprise UI

This architecture becomes the foundation for:

  • dashboards
  • analytics systems
  • SharePoint integrations
  • admin portals
  • CRM systems
  • ERP interfaces
  • Microsoft-style enterprise applications

Create main.tsx

src\main.tsx

import React from "react";
import ReactDOM from "react-dom/client";
import {
FluentProvider,
webLightTheme,
} from "@fluentui/react-components";
import App from "./App";
import "./index.css";
ReactDOM.createRoot(
document.getElementById("root")!
).render(
<React.StrictMode>
<FluentProvider theme={webLightTheme}>
<App />
</FluentProvider>
</React.StrictMode>
);

Create index.css

src\index.css

body {
margin: 0;
font-family: "Segoe UI", Arial, sans-serif;
}
* {
box-sizing: border-box;
}

Run the Application

Development:

npm run dev

Production validation:

npm run build

Production preview:

npm run preview

Complete Rendering Flow

User types username
→ React updates input state
User clicks Search
→ searchUsername updates
Dependency array changes
→ useEffect executes
GitHub API request runs
→ loading state becomes true
Data arrives
→ user state updates
React re-renders
→ GitHubProfileCard appears

Technical Summary

ConceptExplanation
useEffectSynchronizes React with GitHub API
fetch()Executes HTTP requests
async/awaitHandles asynchronous behavior
Loading stateRepresents pending requests
Error stateRepresents failures
Controlled inputReact controls input
Conditional renderingUI derived from state
Fluent UI CardEnterprise presentation
Service layerIsolates API logic
TypeScript interfaceStrong typing

Concept Table

ConceptFileWhy It Matters
API contractGitHubUser.tsStrong typing
Service architecturegithubService.tsClean separation
Controlled inputSearchBar.tsxState-driven forms
Presentational componentGitHubProfileCard.tsxPure rendering
Effect synchronizationApp.tsxExternal systems
Loading UXApp.tsxAsync feedback
Error handlingApp.tsxProduction resilience
Fluent UIMultiple filesEnterprise Microsoft UI

Official Documentation

TopicDocumentation
React LearnReact Learn
Synchronizing with EffectsSynchronizing with Effects
Lifecycle of Reactive EffectsLifecycle of Reactive Effects
You Might Not Need an EffectYou Might Not Need an Effect
GitHub REST APIGitHub REST API
Fluent UI React ComponentsFluent UI React Components
Vite GuideVite Guide
TypeScript DocsTypeScript Docs

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 Style Landing PageCompleted
Block 221Modern CounterCompleted
Block 222Toggle ThemeCompleted
Block 223React CalculatorCompleted
Block 224Login FormCompleted
Block 225User RegistrationCompleted
Block 226Complete ToDo 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 QuizCompleted
Block 239Team ManagerCompleted
Block 240Dynamic DashboardCompleted
Block 341Microsoft Style LoginCompleted
Block 342Corporate FormCompleted
Block 343Tabs NavigationCompleted
Block 344Dialog ManagerCompleted
Block 345Executive DashboardCompleted
Block 346DataGrid CatalogCompleted
Block 347Enterprise User ListCompleted
Block 348Sidebar NavigationCompleted
Block 349Corporate HeaderCompleted
Block 350Professional ToolbarCompleted
Block 351Notification CenterCompleted
Block 352Administrative PanelCompleted
Block 353Ticket ManagerCompleted
Block 354Approval SystemCompleted
Block 355Corporate CalendarCompleted
Block 356SharePoint Inspired DashboardCompleted
Block 357Project DashboardCompleted
Block 358Ticket ControlCompleted
Block 359CRM VisualCompleted
Block 360Corporate ExplorerCompleted
Block 461REST API ConsumptionCompleted
Block 462API DashboardCompleted
Block 463Async SearchCompleted
Block 464GitHub User ExplorerCurrent
Block 465Weather AppNext
Edvaldo Guimrães Filho Avatar

Published by