<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Vishw Patel</title>
    <description>The latest articles on Forem by Vishw Patel (@vishw-patel).</description>
    <link>https://forem.com/vishw-patel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2405778%2F104893de-6ab2-4f59-bfe1-8620a7e421a2.png</url>
      <title>Forem: Vishw Patel</title>
      <link>https://forem.com/vishw-patel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/vishw-patel"/>
    <language>en</language>
    <item>
      <title>How I Deploy My Backend to a VPS (Zero Downtime + Instant Rollbacks,Guide Included)</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Wed, 04 Mar 2026 18:05:16 +0000</pubDate>
      <link>https://forem.com/vishw-patel/how-i-deploy-my-backend-to-a-vps-zero-downtime-instant-rollbacksguide-included-4h46</link>
      <guid>https://forem.com/vishw-patel/how-i-deploy-my-backend-to-a-vps-zero-downtime-instant-rollbacksguide-included-4h46</guid>
      <description>&lt;p&gt;Deploying a backend to a VPS is easy.&lt;/p&gt;

&lt;p&gt;Deploying it &lt;strong&gt;properly&lt;/strong&gt;, with versioning, rollback support, persistent storage, and zero downtime, is what makes a system production-ready.&lt;/p&gt;

&lt;p&gt;In this article, I'll show the exact deployment workflow I use for file converter project &lt;strong&gt;ConvertX&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://convertx.vizzv.com" rel="noopener noreferrer"&gt;https://convertx.vizzv.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This setup gives me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Versioned deployments&lt;/li&gt;
&lt;li&gt;Instant rollback&lt;/li&gt;
&lt;li&gt;Persistent database storage&lt;/li&gt;
&lt;li&gt;Zero-downtime deployment&lt;/li&gt;
&lt;li&gt;Clean release history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the best part: &lt;strong&gt;it works with any backend&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who This Article Is Perfect For
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Indie hackers&lt;/li&gt;
&lt;li&gt;SaaS founders&lt;/li&gt;
&lt;li&gt;Junior backend developers&lt;/li&gt;
&lt;li&gt;Developers moving from localhost to production&lt;/li&gt;
&lt;li&gt;People renting their first VPS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want production reliability without Kubernetes-level complexity, this approach is for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Idea
&lt;/h2&gt;

&lt;p&gt;Instead of deploying directly into one folder like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/var/www/app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It overwrites the same folder every time.This is dangerous.&lt;/p&gt;

&lt;p&gt;Instead, I use a release-based deployment structure. Each deployment creates a &lt;strong&gt;new immutable release&lt;/strong&gt;, and the active version is controlled using a symlink.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A symlink (also called a symbolic link) is a type of file in Linux that points to another file or a folder on your computer. Symlinks are similar to shortcuts in Windows.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This simple idea changes everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Direct Folder Deployments Are Dangerous
&lt;/h2&gt;

&lt;p&gt;When you deploy directly into one folder:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files get partially overwritten&lt;/li&gt;
&lt;li&gt;Old and new code can mix&lt;/li&gt;
&lt;li&gt;Rollbacks are painful&lt;/li&gt;
&lt;li&gt;Failed uploads leave broken states&lt;/li&gt;
&lt;li&gt;Debugging becomes difficult&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If deployment fails mid-upload, your app might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Half old version&lt;/li&gt;
&lt;li&gt;Half new version&lt;/li&gt;
&lt;li&gt;Completely broken&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you won't even know which files changed. That's how production outages happen.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Immutable Releases Matter
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;immutable release&lt;/strong&gt; means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once deployed, it is never modified&lt;/li&gt;
&lt;li&gt;Each version lives in its own folder&lt;/li&gt;
&lt;li&gt;Releases are timestamped&lt;/li&gt;
&lt;li&gt;Old versions stay untouched&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can inspect any past version&lt;/li&gt;
&lt;li&gt;Rollback is instant&lt;/li&gt;
&lt;li&gt;Debugging becomes easier&lt;/li&gt;
&lt;li&gt;No accidental file mutation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern is used by professional deployment tools like Capistrano.&lt;/p&gt;




&lt;p&gt;How This Mimics Capistrano-Style Deployments&lt;/p&gt;

&lt;p&gt;Tools like &lt;strong&gt;Capistrano&lt;/strong&gt; popularized this structure years ago:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
├── releases/
├── shared/
└── current -&amp;gt; releases/version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I simply implement the same architecture manually using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rsync&lt;/li&gt;
&lt;li&gt;symlinks&lt;/li&gt;
&lt;li&gt;PM2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No heavy tooling required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Server Directory Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/root/convertx
├── current → releases/20260117_2120
├── releases
│   ├── 20260104_2031
│   └── 20260117_2120
└── shared
    ├── .env
    └── data
        ├── mydb.sqlite
        ├── uploads
        └── output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Folder Purpose
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Folder&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;releases&lt;/td&gt;
&lt;td&gt;Immutable deployments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;current&lt;/td&gt;
&lt;td&gt;Active running version(symlink)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shared&lt;/td&gt;
&lt;td&gt;Persistent data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.env&lt;/td&gt;
&lt;td&gt;Environment variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;data&lt;/td&gt;
&lt;td&gt;Database &amp;amp; uploads&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;PM2 always runs the application from &lt;code&gt;current&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Symlink Switching Is Atomic in Linux
&lt;/h2&gt;

&lt;p&gt;This is the magic.&lt;/p&gt;

&lt;p&gt;When you run:&lt;br&gt;
&lt;code&gt;ln -sfn releases/NEW_VERSION current&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Linux replaces the symlink atomically.&lt;br&gt;
That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is no intermediate broken state&lt;/li&gt;
&lt;li&gt;The pointer changes instantly&lt;/li&gt;
&lt;li&gt;The filesystem guarantees consistency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5rd70405m2hwuhoapo3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5rd70405m2hwuhoapo3t.png" alt="Symlink example" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the OS perspective, the switch happens in one operation.&lt;br&gt;
That's how zero-downtime switching works.&lt;/p&gt;


&lt;h2&gt;
  
  
  Deployment Flow
&lt;/h2&gt;

&lt;p&gt;The deployment process looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Local Machine
    ↓
Build project
    ↓
Create release folder
    ↓
Upload via rsync
    ↓
Link shared files
    ↓
Switch "current" symlink
    ↓
Restart PM2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use pm2 reload to avoid downtime. The new version becomes live immediately. The previous version still exists inside &lt;code&gt;releases/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This allows a new version to go live &lt;strong&gt;instantly&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens If Deployment Fails Mid-Upload?
&lt;/h2&gt;

&lt;p&gt;Nothing breaks.&lt;/p&gt;

&lt;p&gt;Why?&lt;br&gt;
Because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload happens inside a new release folder&lt;/li&gt;
&lt;li&gt;current is not touched during upload&lt;/li&gt;
&lt;li&gt;The live app keeps running&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If upload fails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delete the incomplete release&lt;/li&gt;
&lt;li&gt;Redeploy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your live application is never affected.&lt;/p&gt;
&lt;h2&gt;
  
  
  Rollbacks in Seconds
&lt;/h2&gt;

&lt;p&gt;If something goes wrong after switching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-sfn&lt;/span&gt; /root/convertx/releases/OLD_VERSION /root/convertx/current
pm2 restart convertx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rollback time: under 5 seconds.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No rebuilding.&lt;/li&gt;
&lt;li&gt;No reinstalling.&lt;/li&gt;
&lt;li&gt;No panic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just switch the symlink.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack Used
&lt;/h2&gt;

&lt;p&gt;For this deployment workflow I use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bun runtime&lt;/li&gt;
&lt;li&gt;PM2&lt;/li&gt;
&lt;li&gt;Nginx reverse proxy&lt;/li&gt;
&lt;li&gt;SQLite&lt;/li&gt;
&lt;li&gt;rsync for fast deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stack is simple, cheap, and extremely reliable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security Practices
&lt;/h2&gt;

&lt;p&gt;Some important security rules I follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.env&lt;/code&gt; is never uploaded&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node_modules&lt;/code&gt; is never uploaded&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data/&lt;/code&gt; stays persistent&lt;/li&gt;
&lt;li&gt;SSH keys only (no password login)&lt;/li&gt;
&lt;li&gt;HTTPS handled via Nginx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps secrets and data safe during deployments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Automatic File Cleanup
&lt;/h2&gt;

&lt;p&gt;ConvertX processes uploaded files, so temporary files must be removed periodically.&lt;/p&gt;

&lt;p&gt;I implemented two cleanup systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Internal scheduler in the application&lt;/li&gt;
&lt;li&gt;System cron fallback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures storage never grows uncontrollably.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Not Docker?
&lt;/h2&gt;

&lt;p&gt;Docker is great.&lt;/p&gt;

&lt;p&gt;For small single-service VPS deployments, Docker may not provide enough benefit to justify its operational overhead.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds complexity&lt;/li&gt;
&lt;li&gt;Requires image builds&lt;/li&gt;
&lt;li&gt;Adds extra layer of debugging&lt;/li&gt;
&lt;li&gt;Consumes more memory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For simple backend services, native runtime + PM2 is often enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Not CI/CD Pipelines?
&lt;/h2&gt;

&lt;p&gt;CI/CD is powerful.&lt;/p&gt;

&lt;p&gt;But for solo builders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds setup time&lt;/li&gt;
&lt;li&gt;Adds moving parts&lt;/li&gt;
&lt;li&gt;Can obscure what actually happens on the server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Manual release-based deployment is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transparent&lt;/li&gt;
&lt;li&gt;Predictable&lt;/li&gt;
&lt;li&gt;Easy to debug&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can always add CI later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Not Git-Based Deployment?
&lt;/h2&gt;

&lt;p&gt;Some deploy with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git pull origin main&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This has problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No version isolation&lt;/li&gt;
&lt;li&gt;Harder rollback&lt;/li&gt;
&lt;li&gt;Risk of merge conflicts on server&lt;/li&gt;
&lt;li&gt;Repository becomes mutable production state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Production should not be your working directory. Releases solve this cleanly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Deployment Strategy Works
&lt;/h2&gt;

&lt;p&gt;Benefits of this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero-downtime deployment&lt;/li&gt;
&lt;li&gt;Safe rollbacks&lt;/li&gt;
&lt;li&gt;Clean release history&lt;/li&gt;
&lt;li&gt;Persistent storage&lt;/li&gt;
&lt;li&gt;Easy debugging&lt;/li&gt;
&lt;li&gt;Production-grade workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it works on any VPS.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;A lot of developers over-complicate deployments with heavy infrastructure.&lt;/p&gt;

&lt;p&gt;But with rsync + symlinks + PM2, you can build a very reliable deployment pipeline on a simple VPS.&lt;/p&gt;

&lt;p&gt;Sometimes the best solutions are the simplest ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;This is exact guide, I use for deployment for &lt;code&gt;convertx&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## Server Directory Structure

/`/`/`

/root/convertx
├── current → releases/20260117_2120
├── releases
│   ├── 20260104_2031
│   └── 20260117_2120
└── shared
├── .env
└── data
├── mydb.sqlite
├── uploads
└── output

/`/`/`

### Rules
- `shared/` → persistent files
- `releases/` → immutable deployments
- `current` → active version (symlink)
- PM2 always runs from `current`

---

# FIRST TIME DEPLOYMENT

---

## 1.Build Locally

/`/`/`bash
bun install
bun run build
/`/`/`

(If build is not required, skip.)

---

## 2.Create New Release (Local)

/`/`/`bash
cd ~/deployment/convertX/releases

TS=$(date +%Y%m%d_%H%M)
mkdir $TS
/`/`/`

Copy project files:

/`/`/` bash
rsync -av \
  --exclude node_modules \
  --exclude data \
  --exclude .git \
  ~/opensource/ConvertX/ \
  ~/deployment/convertX/releases/$TS/
/`/`/`

---

## 3.Upload Release to Server

/`/`/`bash
rsync -avz \
  --exclude node_modules \
  --exclude data \
  --exclude .git \
  ~/deployment/convertX/releases/$TS/ \
  root@SERVER_IP:/root/convertx/releases/$TS/
/`/`/`

---

## 4.Link Shared Files (Server)

/`/`/`bash
ssh root@SERVER_IP
/`/`/`

/`/`/`bash
cd /root/convertx/releases/$TS

ln -s ../../shared/.env .env
ln -s ../../shared/data data
/`/`/`

---

## 5.Activate Release

/`/`/`bash
ln -sfn /root/convertx/releases/$TS /root/convertx/current
/`/`/`

---

## 6.Install Dependencies

/`/`/`bash
cd /root/convertx/current
bun install
/`/`/`

---

## 7.Restart Application

/`/`/`bash
pm2 restart convertx
/`/`/`

---

## 8.Verify Deployment

/`/`/`bash
pm2 status
/`/`/`

/`/`/`bash
curl -H "Authorization: Bearer API_TOKEN" \
https://api.com/api/health
/`/`/`

---

# DEPLOYING A NEW RELEASE

Repeat the same flow.

---

## Local

/`/`/`bash
TS=$(date +%Y%m%d_%H%M)

mkdir ~/deployment/convertX/releases/$TS

rsync -av \
  --exclude node_modules \
  --exclude data \
  --exclude .git \
  ~/opensource/ConvertX/ \
  ~/deployment/convertX/releases/$TS/
/`/`/`

---

## Upload

/`/`/`bash
rsync -avz \
  --exclude node_modules \
  --exclude data \
  --exclude .git \
  ~/deployment/convertX/releases/$TS/ \
  root@SERVER_IP:/root/convertx/releases/$TS/
/`/`/`

---

## Server

/`/`/`bash
cd /root/convertx/releases/$TS

ln -s ../../shared/.env .env
ln -s ../../shared/data data

ln -sfn /root/convertx/releases/$TS /root/convertx/current

cd /root/convertx/current
bun install
pm2 restart convertx
/`/`/`

---

# ROLLBACK

If deployment fails:

/`/`/`bash
ln -sfn /root/convertx/releases/OLD_TIMESTAMP /root/convertx/current
pm2 restart convertx
/`/`/`

Rollback time: **&amp;lt; 5 seconds**

---

# CLEAN OLD RELEASES

Keep last 3–5 releases.

/`/`/`bash
cd /root/convertx/releases
ls
rm -rf OLD_TIMESTAMP
/`/`/`

Never delete `current`.

---

# SECURITY NOTES

* Never upload `.env`
* Never upload `data/`
* Never upload `node_modules`

---

# PM2 COMMANDS

/`/`/` bash
pm2 status
pm2 logs convertx
pm2 restart convertx
pm2 save
pm2 startup
/`/`/`

---

**ConvertX deployment is live. 🚀**

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devops</category>
      <category>vps</category>
      <category>pm2</category>
    </item>
    <item>
      <title>How We Built Secure Cross-App SSO for Multi-Tenant Financial Application : Architecture, Risks, and Lessons</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Thu, 12 Feb 2026 12:46:56 +0000</pubDate>
      <link>https://forem.com/vishw-patel/how-we-built-secure-cross-app-sso-for-multitanent-financial-application-architecture-risks-and-4gd2</link>
      <guid>https://forem.com/vishw-patel/how-we-built-secure-cross-app-sso-for-multitanent-financial-application-architecture-risks-and-4gd2</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;For the past two years, I've been working on a large-scale multi-tenant financial platform serving 250+ financial institutions across the U.S. The system supports millions of end users, with around 50-60k monthly active users interacting across different portals.&lt;/p&gt;

&lt;p&gt;Recently, we implemented a &lt;strong&gt;secure cross-application SSO&lt;/strong&gt; flow between our admin operations portal and a dedicated reporting dashboard. What initially looked like a simple "View Dashboard" button turned into a deeper architectural challenge involving tenant isolation, token exchange, and strict access boundaries — where errors are costly, user trust is critical, and sensitive financial data is always at stake.&lt;/p&gt;

&lt;p&gt;Before diving into SSO, it's important to understand how the platform itself is structured.&lt;/p&gt;




&lt;h2&gt;
  
  
  High-Level Architecture: Three Portals, Three Responsibilities
&lt;/h2&gt;

&lt;p&gt;Our system isn't a single monolithic app. It consists of three independent portals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Customer Portal&lt;/strong&gt; - used by end users interacting with financial products.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin &amp;amp; Operations Portal&lt;/strong&gt; - used internally to manage multiple tenants (financial institutions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reporting Dashboard&lt;/strong&gt; - focused on KPIs, analytics, and performance reporting.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each portal has its own purpose, deployment lifecycle, and trust boundary. Separation allowed our team (compact 7-engineer group owning everything from architecture and design to development, testing, and deployment) to scale independently and reduced the risk of exposing sensitive reporting functionality directly inside operational workflows.&lt;/p&gt;

&lt;p&gt;From a technology standpoint, we used &lt;strong&gt;React&lt;/strong&gt; for the frontend and &lt;strong&gt;.NET&lt;/strong&gt; for the backend.&lt;/p&gt;

&lt;p&gt;From an identity perspective, this also meant authentication couldn't be tightly coupled to one application - especially in a multi-tenant setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three Types of Users
&lt;/h2&gt;

&lt;p&gt;Our architecture revolves around three main user roles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Customers - interact only with the customer portal.&lt;/li&gt;
&lt;li&gt;Financial Institution (FI) Employees - log directly into the reporting dashboard using username/password.&lt;/li&gt;
&lt;li&gt;Admins - operate from the admin portal and also require access into reporting for operation purposes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The reporting dashboard was originally designed only for FI employees and single-tenant access patterns. Later, due to operational requirements, we needed to extend it to support both Admins and FI employees.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fattxn4f82vxsrof1f5ic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fattxn4f82vxsrof1f5ic.png" width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;Fig.1 - Overview of portals and user roles showing access boundaries.
  &lt;/p&gt;




&lt;h2&gt;
  
  
  New Requirement
&lt;/h2&gt;

&lt;p&gt;Admins have a simple "Reporting" button. On clicking it, they should be redirected to the Reporting Portal in a new tab without logging in again.&lt;/p&gt;

&lt;p&gt;Admins already have higher privileges and multi-tenant roles, which complicates seamless access while maintaining strict isolation between tenants. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Problem introduced with requirement
&lt;/h2&gt;

&lt;p&gt;At first, this sounded like a simple redirect problem. In reality, it introduced deeper architectural questions around identity boundaries and tenant safety.&lt;/p&gt;

&lt;p&gt;Admins operate the Admin &amp;amp; Operations Portal and can manage multiple financial institutions (FIs). When performing actions, they select a tenant and operate under that FI context.&lt;/p&gt;

&lt;p&gt;With the new requirement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admins expect instant access to the tenant's reporting environment.&lt;/li&gt;
&lt;li&gt;Tenant isolation must be preserved: the Reporting Portal should only allow access to the currently selected FI.&lt;/li&gt;
&lt;li&gt;We currently use JWT tokens in both portals to store access and role information.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Challenges:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Maintain strict tenant isolation - an admin should not access data from another FI just because they have global privileges.&lt;/li&gt;
&lt;li&gt;Avoid sharing sessions directly between apps - no session cookies or tokens should be blindly reused.&lt;/li&gt;
&lt;li&gt;Prevent long-lived tokens from leaking across domains, which could compromise data security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Problem with reusing Admin JWT:
&lt;/h4&gt;

&lt;p&gt;Using the Admin JWT in the Reporting Portal would blur tenant boundaries. It risks cross-tenant data leaks, defeating the purpose of isolated reporting per FI.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSO Solution: How We Enabled Secure Cross-App Access
&lt;/h2&gt;

&lt;p&gt;Once we clearly understood the risks around tenant isolation and cross-application authentication, the goal became simple to define but harder to execute: enable admins to move from the operations portal to the reporting dashboard seamlessly - without sharing sessions directly or weakening security boundaries. It was about connecting two independent applications without breaking tenant isolation or expanding trust boundaries.&lt;/p&gt;

&lt;h4&gt;
  
  
  Overall Approach
&lt;/h4&gt;

&lt;p&gt;Instead of sharing sessions or forwarding existing admin tokens, we implemented a token exchange based SSO flow. The admin portal initiates the process, but the reporting application ultimately issues and owns its own authentication token. This allowed each portal to remain autonomous while still providing a unified experience to the user.&lt;/p&gt;

&lt;p&gt;The core principle behind the design was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Never transfer long-lived identity between applications - exchange it for a new, purpose-built token.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Admin Portal Login Flow (Before SSO)
&lt;/h4&gt;

&lt;p&gt;Before diving into the SSO flow, let's first understand how the Admin Portal login works in our system.&lt;/p&gt;

&lt;p&gt;Step 1: Admin Authentication&lt;/p&gt;

&lt;p&gt;Admins log in using a username and password. Behind the scenes, our custom Identity Server handles authentication. When credentials are submitted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Identity Server validates the admin.&lt;/li&gt;
&lt;li&gt;If authentication succeeds, it issues a JWT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This initial token contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin metadata&lt;/li&gt;
&lt;li&gt;A list of accessible banks&lt;/li&gt;
&lt;li&gt;High-level permissions and claims&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, the token is not scoped to a specific bank.&lt;/p&gt;

&lt;p&gt;Step 2: Bank Selection&lt;/p&gt;

&lt;p&gt;After login, the admin is presented with a list of banks they are authorized to manage.&lt;/p&gt;

&lt;p&gt;When the admin selects a bank:&lt;/p&gt;

&lt;p&gt;The frontend sends a request to the Identity Server with the selected &lt;code&gt;bankGuid&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The Identity Server verifies whether the admin has permission to access that specific bank.&lt;/p&gt;

&lt;p&gt;If authorized, a new JWT is generated - this time scoped to the selected bank. The new token includes bank-level permissions and context. The token is returned to the admin.&lt;/p&gt;

&lt;p&gt;The frontend then replaces the initial token with this bank-scoped token and uses it for all subsequent API requests.&lt;/p&gt;

&lt;p&gt;Why We Use &lt;code&gt;bankGuid&lt;/code&gt; Instead of Primary Keys&lt;/p&gt;

&lt;p&gt;We never expose actual database primary keys to the UI.&lt;/p&gt;

&lt;p&gt;Instead, we use temporary, globally unique identifiers (bankGuid) that map internally to bankId.&lt;/p&gt;

&lt;p&gt;Key characteristics of this mapping:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically generated&lt;/li&gt;
&lt;li&gt;Globally unique&lt;/li&gt;
&lt;li&gt;Refreshed approximately every 30 minutes&lt;/li&gt;
&lt;li&gt;New GUIDs are reassigned after refresh&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An abstraction layer between UI and database&lt;/li&gt;
&lt;li&gt;Protection against direct ID enumeration&lt;/li&gt;
&lt;li&gt;Reduced risk of exposing internal data structures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Token Expiry and Seamless Refresh&lt;/p&gt;

&lt;p&gt;Bank-scoped JWTs expire after &lt;code&gt;~20 minutes&lt;/code&gt;. To maintain uninterrupted access: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The frontend uses a refresh token to request a new access token when the current one expires.&lt;/li&gt;
&lt;li&gt;If the bank’s bankGuid has rotated in the meantime, the new token contains the current valid GUID.&lt;/li&gt;
&lt;li&gt;Any request made with an old token automatically triggers this refresh flow. The new token replaces the old one transparently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No broken sessions&lt;/li&gt;
&lt;li&gt;No manual re-login required&lt;/li&gt;
&lt;li&gt;Continuous, secure access under the correct bank context&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;bankGuid&lt;/code&gt; rotation is designed to minimize exposure of stable internal IDs, and does not invalidate active sessions. During token refresh, the current valid bankGuid is always issued to ensure seamless continuity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since each JWT is scoped to a single bank:&lt;/p&gt;

&lt;p&gt;The admin operates strictly within one bank context at a time. Opening multiple tabs does not allow simultaneous operation across different banks under the same session. In financial systems, &lt;code&gt;"context confusion"&lt;/code&gt; is a real risk. An admin believing they are working in Bank A while modifying Bank B is not a theoretical problem - it’s an operational nightmare.&lt;/p&gt;

&lt;p&gt;By enforcing bank-scoped tokens, we eliminate context confusion and significantly reduce the risk of unintended changes across financial institutions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqx9okrkd79u31n6tj1hg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqx9okrkd79u31n6tj1hg.png" width="800" height="803"&gt;&lt;/a&gt;&lt;br&gt;Fig.2 - Admin Authentication Flow.
  &lt;/p&gt;

&lt;p&gt;With bank-scoped tokens firmly established in the Admin Portal, the next challenge was securely extending this tenant context to the Reporting Dashboard without compromising isolation or security boundaries.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Token Exchange Flow: Step-by-Step
&lt;/h4&gt;

&lt;p&gt;Once the admin is authenticated and the bank-scoped JWT is issued, the next task is to securely extend the admin's session to the Reporting Portal while maintaining tenant isolation. Instead of transferring the long-lived bank-scoped JWT between applications, we implemented a token exchange flow to ensure security boundaries are respected.&lt;/p&gt;

&lt;p&gt;Here's a detailed breakdown of how it works:&lt;/p&gt;

&lt;p&gt;Step 1: Admin Requests Access to Reporting&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The admin clicks the "Reporting" button on the dashboard.&lt;/li&gt;
&lt;li&gt;The admin frontend sends a Single Sign-On (SSO) token request to the admin backend, including the bank context extracted from the JWT stored in local storage.&lt;/li&gt;
&lt;li&gt;The admin backend forwards the token to the identity server.&lt;/li&gt;
&lt;li&gt;The identity server validates the token and checks the admin’s permissions for accessing the reporting system.&lt;/li&gt;
&lt;li&gt;If valid, the identity server creates a short-lived, encrypted token (2-minute expiry) containing the admin info and bank context, then returns it to the admin backend.&lt;/li&gt;
&lt;li&gt;The admin backend forwards this short-lived SSO token to the admin frontend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Step 2: Redirect to Reporting Dashboard&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The admin frontend opens the Reporting Dashboard in a new browser tab, sending the short-lived SSO token along with the request.&lt;/li&gt;
&lt;li&gt;The request reaches the reporting frontend, which passes it to the reporting backend.&lt;/li&gt;
&lt;li&gt;The reporting backend sends the SSO token to the identity server for verification.&lt;/li&gt;
&lt;li&gt;Upon validation, the identity server issues a new JWT containing the admin’s reporting permissions and bank context.&lt;/li&gt;
&lt;li&gt;The reporting frontend uses this new JWT for all subsequent requests, ensuring secure access without ever exposing the long-lived bank-scoped JWT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv1xtpm2lpxdeab2e57iu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv1xtpm2lpxdeab2e57iu.png" width="800" height="725"&gt;&lt;/a&gt;&lt;br&gt;Fig.3 - Token Exchange Flow.
  &lt;/p&gt;

&lt;p&gt;Why This Approach Works&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tenant Isolation&lt;/strong&gt;: The admin's bank context is always scoped to the reporting system.&lt;br&gt;
&lt;strong&gt;Short-lived Tokens&lt;/strong&gt;: Minimize exposure of sensitive credentials during redirects.&lt;br&gt;
&lt;strong&gt;Centralized Validation&lt;/strong&gt;: The identity server enforces permissions at every stage, ensuring only authorized access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edge Case: Context Confusion Across Multiple Tabs
&lt;/h2&gt;

&lt;p&gt;You might think the token exchange flow is bulletproof and technically, it is. Strict tenant isolation, short-lived tokens, and carefully scoped permissions make cross-bank data leaks practically impossible. But here's the twist: sometimes, it’s the human — not the code — who becomes the weak link.&lt;/p&gt;

&lt;p&gt;Picture this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An admin logs into the Admin Portal and selects Bank A.&lt;/li&gt;
&lt;li&gt;He/She click the Reporting button, opening Bank A's Reporting Dashboard in a new tab - all good.&lt;/li&gt;
&lt;li&gt;Then, the admin goes back to the Admin Portal, navigates to the home page, and switches to Bank B.&lt;/li&gt;
&lt;li&gt;He/She click Reporting again, opening Bank B's Reporting Dashboard in a second tab.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first tab still shows Bank A's dashboard.&lt;/li&gt;
&lt;li&gt;The second tab shows Bank B's dashboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system is doing exactly what it should: both dashboards enforce correct bank-level access, and the backend has kept each tenant neatly separated.&lt;/p&gt;

&lt;p&gt;However, the user could get confused, thinking that both tabs are linked to the same bank context or confuse between banks. This may lead to operational mistakes, like performing actions in Bank B while thinking they are in Bank A.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Even with strict backend isolation, UX design must reinforce tenant boundaries to prevent &lt;code&gt;"context confusion"&lt;/code&gt; that could lead to mistakes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Mitigation: Real-Time Tab Coordination
&lt;/h2&gt;

&lt;p&gt;Even with single-session rules, admins may already have a reporting tab open when they try to open another. To handle this smoothly and prevent confusion, we implemented cross-tab messaging:&lt;code&gt;Broadcasting Events Between Tabs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We use the browser's Broadcast Channel API to send messages to all open tabs of the same application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a new reporting session starts, the reporting frontend broadcasts a "reporting session started" message to all other tabs.&lt;/li&gt;
&lt;li&gt;Upon receiving the broadcast, any previous reporting tab automatically logs out the active reporting session.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures only one reporting session per browser at any time.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tradeoffs
&lt;/h4&gt;

&lt;p&gt;Implementing a secure, token-exchange SSO with strict tenant isolation isn't free - it comes with tradeoffs that are worth acknowledging.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt; :&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Each SSO flow involves extra redirects and token validation steps.&lt;/li&gt;
&lt;li&gt;We accepted this tradeoff because correctness, security, and tenant isolation outweigh shaving milliseconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Over-Trusting Tokens&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Tokens must never be blindly trusted across applications or sessions.&lt;/li&gt;
&lt;li&gt;Sharing tokens between portals would break tenant boundaries and risk sensitive data exposure.&lt;/li&gt;
&lt;li&gt;The token-exchange flow mitigates this, but it requires careful validation, short lifetimes, and consistent backend enforcement.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;User Experience vs Security&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Enforcing one reporting session per device prevents context confusion but may frustrate admins who are used to opening multiple tabs, but it's a UX compromise to maintain security.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Implementation Complexity&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Adding token exchange, session invalidation, and cross-tab messaging adds more moving parts.&lt;/li&gt;
&lt;li&gt;Each component must be carefully tested to avoid race conditions, token mismatches, or failed SSO flows.&lt;/li&gt;
&lt;li&gt;For a small team, this increases maintenance overhead, but it's necessary for enterprise-grade multi-tenant security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lesson Learned :
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Even with rock-solid backend isolation, UX design acts as the guardian.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From this experience, we realized:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technical safeguards aren't enough: No matter how airtight your token exchange or permission model is, users can still get confused.&lt;/li&gt;
&lt;li&gt;Cross-tab coordination is essential: Real-time messaging between tabs prevents &lt;code&gt;"ghost sessions"&lt;/code&gt; and reduces operational mistakes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Designing secure cross-application SSO in a multi-tenant financial system pushed us to think far beyond simple redirects and token handling. It required clear trust boundaries, purpose-built token exchange instead of shared identity, strict tenant scoping, controlled session invalidation, and thoughtful UX decisions to prevent context confusion. In environments where sensitive financial data is involved, even small architectural shortcuts can lead to serious consequences, so every layer (identity server, token lifecycle, tenant mapping, and frontend behavior) must work together intentionally. SSO is not just about seamless access; it is about enforcing boundaries while preserving usability. When built correctly, it becomes a disciplined bridge between independent systems rather than a shortcut around authentication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep learning, keep growing.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>architecture</category>
      <category>authetication</category>
      <category>sso</category>
    </item>
    <item>
      <title>Don't call your self react developer until you don't know this</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Tue, 29 Apr 2025 09:22:10 +0000</pubDate>
      <link>https://forem.com/vishw-patel/dont-call-your-self-react-developer-until-you-dont-know-this-5gd0</link>
      <guid>https://forem.com/vishw-patel/dont-call-your-self-react-developer-until-you-dont-know-this-5gd0</guid>
      <description>&lt;h2&gt;
  
  
  How React Works Under the Hood
&lt;/h2&gt;

&lt;p&gt;React may seem magical, but behind the scenes, it's a highly optimized and elegant system.&lt;/p&gt;

&lt;p&gt;In this comprehensive deep dive, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What React DOM really does&lt;/li&gt;
&lt;li&gt;How JSX is parsed into JavaScript objects&lt;/li&gt;
&lt;li&gt;Why every component is just a function or object&lt;/li&gt;
&lt;li&gt;The diffing and reconciliation process&lt;/li&gt;
&lt;li&gt;How Hooks like &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; really work&lt;/li&gt;
&lt;li&gt;Optimization strategies React uses&lt;/li&gt;
&lt;li&gt;React Fiber: the heart of the React rendering engine&lt;/li&gt;
&lt;li&gt;How to build your own mini React&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s decode the internals &lt;/p&gt;

&lt;h2&gt;
  
  
  1. React DOM: The Rendering Engine
&lt;/h2&gt;

&lt;p&gt;React is a powerful JavaScript library for building user interfaces, but it doesn't interact directly with the browser's Document Object Model (DOM). That crucial responsibility is handled by &lt;strong&gt;ReactDOM&lt;/strong&gt;, which serves as the rendering engine that connects React's declarative component model to the actual browser environment. When developers write a command like &lt;code&gt;ReactDOM.render(&amp;lt;App /&amp;gt;, document.getElementById('root'));&lt;/code&gt;, they're instructing ReactDOM to take the virtual component tree and mount it into the specified location in the real DOM. Behind the scenes, ReactDOM creates a &lt;code&gt;virtual representation&lt;/code&gt; of the UI elements, compares them during updates using a diffing algorithm, and applies only the minimal set of changes needed to the real DOM — improving performance and responsiveness.&lt;/p&gt;

&lt;p&gt;ReactDOM's strength lies in its ability to efficiently manage host environment logic, meaning it knows how to interact with browser-specific APIs like &lt;code&gt;document.createElement&lt;/code&gt;, &lt;code&gt;appendChild&lt;/code&gt;, or &lt;code&gt;removeChild&lt;/code&gt;. This separation of concerns allows React itself to remain platform-agnostic — enabling other renderers like React Native or React 360 — while ReactDOM is specifically tailored for web browsers. By handling DOM interactions, event delegation, and mounting lifecycle logic, ReactDOM plays a critical role in making React applications feel fast, interactive, and modern.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. How JSX Works Internally
&lt;/h2&gt;

&lt;p&gt;JSX may look like regular HTML, but it's actually a JavaScript syntax extension that simplifies how we write React components. Instead of manually calling JavaScript functions to create DOM elements, JSX allows us to write components in a familiar, HTML-like structure. But here's the catch: JSX doesn’t directly work in the browser. It’s converted into JavaScript before the browser can run it. JSX is essentially syntactic sugar, meaning it makes writing code easier, but it still gets converted into something else under the hood.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxor98lmta82ifaarpe08.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxor98lmta82ifaarpe08.png" alt="JSX to react component" width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
Let’s break it down with a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;div&amp;gt;Hello, world!&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, this looks like regular HTML. But when JSX is compiled by tools like Babel, it gets turned into a JavaScript function call like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React.createElement('div', null, 'Hello, world!');

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This may seem confusing at first, but what’s happening here is that React.createElement is a function that React uses to create a virtual representation of the UI you’re building. In this case, it’s creating an object that describes the &lt;/p&gt; element, its attributes (none in this case), and its content (the text 'Hello, world!').

&lt;p&gt;&lt;strong&gt;Why Do We Use JSX?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JSX makes React development more intuitive and less verbose. Imagine creating a list of items in pure JavaScript without JSX:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const list = React.createElement('ul', null, 
  React.createElement('li', null, 'Item 1'),
  React.createElement('li', null, 'Item 2'),
  React.createElement('li', null, 'Item 3')
);
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This looks cumbersome compared to the JSX version:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ul&amp;gt;
  &amp;lt;li&amp;gt;Item 1&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;Item 2&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;Item 3&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;As you can see, JSX provides a cleaner, more readable way to write React components. And under the hood, it’s just a simpler, more intuitive way to call &lt;code&gt;React.createElement&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Components Are Objects or Functions
&lt;/h2&gt;

&lt;p&gt;In React, components are the building blocks of your application. A component is a reusable piece of code that defines part of the UI. You can think of a component as a function or a class, both of which return a description of what the UI should look like. This description is what React will use to create the actual user interface in the browser. So, when you create components, you’re basically writing a function or class that returns what the UI should look like at that moment.&lt;/p&gt;

&lt;p&gt;Function Components&lt;br&gt;
Let’s start with &lt;strong&gt;function components&lt;/strong&gt;, which are simpler and more common in modern React development .A function component is just a function that returns JSX. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function MyButton() {
  return &amp;lt;button&amp;gt;Click me&amp;lt;/button&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;In this example, MyButton is a function that returns a JSX element a &amp;lt;button&amp;gt; element with the text &lt;code&gt;Click me&lt;/code&gt;. This function component looks simple, but when it’s rendered, React does a lot behind the scenes. It takes this JSX, converts it into a &lt;strong&gt;virtual DOM node&lt;/strong&gt;, and eventually updates the real DOM on the page.&lt;/p&gt;

&lt;p&gt;Now, when you call the MyButton component in JSX like this:&lt;code&gt;&amp;lt;MyButton&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;React doesn’t directly render it to the page. Instead, it takes the JSX and creates a JavaScript object that represents the component. This object looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MyButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This object has two important properties:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;type&lt;/strong&gt;: This refers to the component itself (MyButton).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;props&lt;/strong&gt;: This refers to the properties (or "props") passed to the component. In this case, there are no props passed, so it's an empty object.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How React Uses Components&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;React uses both function and class components in a similar way. Whether you define your component as a function or a class, React calls the component to get the description of the UI (the JSX), then builds a tree of virtual DOM nodes. This process is recursive — meaning if you have a component that contains other components, React will also create virtual DOM nodes for those components.&lt;/p&gt;

&lt;p&gt;For example, let’s say you have a parent component and a child component:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function Parent() {
  return &amp;lt;MyButton /&amp;gt;;
}

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Here, React will first create the virtual DOM node for the Parent component. Then, it will call the MyButton component inside the Parent component and create the virtual DOM node for it too. It does this recursively, meaning if components are nested, React will go through each one to build the complete tree of virtual DOM nodes.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Reconciliation and Virtual DOM
&lt;/h2&gt;

&lt;p&gt;One of the main reasons React is known for its performance is its reconciliation algorithm and the use of the Virtual DOM. But what does this mean, and how does it help make React fast and efficient? Let's break it down step by step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the Virtual DOM?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To understand how React updates the real DOM efficiently, we first need to understand the &lt;strong&gt;Virtual DOM&lt;/strong&gt;. The Virtual DOM is a lightweight, in-memory representation of the real DOM. It’s essentially a copy of the UI, but it’s not the actual elements on the page. React uses this virtual representation to figure out what changes need to be made to the real DOM, without directly manipulating it right away. This saves a lot of time and resources because interacting with the real DOM can be slow, especially when there are many elements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When State Changes&lt;/strong&gt;&lt;br&gt;
Now, let’s say something changes in your app, such as when a user clicks a button or enters text in an input field. This is a state change, and when state changes, React follows these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rebuild the Virtual DOM&lt;/strong&gt;: React re-renders the component and rebuilds the entire Virtual DOM tree. This means React creates a new in-memory copy of the UI based on the updated state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare the Virtual DOMs&lt;/strong&gt;: React then compares the newly created Virtual DOM tree to the previous one. This comparison helps React figure out what has changed between the two.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply Necessary Updates&lt;/strong&gt;: After React has identified the differences, it applies only the necessary updates to the real DOM. React doesn’t update the entire real DOM — just the parts that have changed. This process is called reconciliation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5r14zp9dxo70difa263.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg5r14zp9dxo70difa263.png" alt="Virtual Dom Comparision" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Reconciliation Works&lt;/strong&gt;&lt;br&gt;
React's reconciliation process follows specific rules to make updates efficient. Let’s go through them one by one:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Elements of Different Types&lt;/strong&gt;: If the type of the element has changed (for example, if a  is replaced by a &lt;span&gt;), React will completely replace the existing DOM node with a new one. This ensures that React doesn’t try to keep any unnecessary information when the structure changes.


&lt;p&gt;For example, if you change a &amp;lt;div&amp;gt; to a &amp;lt;button&amp;gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;Click me&amp;lt;/div&amp;gt; // Previous
&amp;lt;button&amp;gt;Click me&amp;lt;/button&amp;gt; // Updated

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;React will replace the entire &amp;lt;div&amp;gt; node with a new &amp;lt;button&amp;gt; node.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Same Type&lt;/strong&gt;: If the element type is the same (for example, a &amp;lt;div&amp;gt; to another &amp;lt;div&amp;gt;), React will update the existing element’s props and children. React only updates the things that need to be updated. This makes updates much faster than creating a whole new element.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For instance, if you change the text inside a &amp;lt;div&amp;gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;Hello&amp;lt;/div&amp;gt; // Previous
&amp;lt;div&amp;gt;Goodbye&amp;lt;/div&amp;gt; // Updated

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;React will just update the text inside the same &amp;lt;div&amp;gt; element, rather than creating a whole new element.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Children Need Keys for List Diffing&lt;/strong&gt;: When working with lists of elements (like in a list or a table), React needs a way to keep track of each item in the list when the list changes. For this, React uses keys. A key is a unique identifier that helps React match the old items in the list with the new ones.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, consider this list of items:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ul&amp;gt;
  &amp;lt;li&amp;gt;Item 1&amp;lt;/li&amp;gt;
  &amp;lt;li&amp;gt;Item 2&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

If you change the order or remove items from the list, React needs a way to keep track of which item is which. Without keys, React might get confused about which item should be updated and might not perform updates correctly. That’s why you should always provide a unique key for each item in a list:

&lt;/code&gt;&lt;/pre&gt;



&lt;ul&gt;
  &lt;li&gt;Item 1&lt;/li&gt;
  &lt;li&gt;Item 2&lt;/li&gt;
&lt;/ul&gt;



&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
By providing keys, React can efficiently update the list when changes occur, reducing unnecessary re-renders and keeping the UI in sync with the data.
&lt;/code&gt;&lt;/pre&gt;



&lt;h2&gt;
  
  
  5. Hooks Internals
&lt;/h2&gt;

&lt;p&gt;React Hooks like &lt;strong&gt;useState&lt;/strong&gt;, &lt;strong&gt;useEffect&lt;/strong&gt;, and others may seem like magic at first, but under the hood, their logic is surprisingly elegant. Understanding how they work internally not only gives you more confidence while coding, but also helps avoid common mistakes like using hooks conditionally or inside loops.&lt;/p&gt;

&lt;p&gt;Let’s break it down step by step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concept: Hooks as State Slots&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you use hooks like useState, React manages state without classes. Instead, it internally keeps track of an &lt;strong&gt;array of state values&lt;/strong&gt; (or “slots”) for each functional component. Each time your component renders, React walks through that array, calling your hooks in the exact same order.&lt;/p&gt;

&lt;p&gt;Here’s a simplified version of how useState might work behind the scenes:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let hookIndex = 0;
const hooks = [];

function useState(initial) {
  const currentHook = hooks[hookIndex] ?? initial;

  const setState = (newValue) =&amp;gt; {
    hooks[hookIndex] = newValue;
    rerender(); // Re-render the component when state changes
  };

  hookIndex++;
  return [currentHook, setState];
}

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This example assumes a global hookIndex and hooks array. Every time the component renders, hookIndex resets to 0, and React walks through the hooks in the same order they were declared. When you call useState(), it looks at the hooks[0] slot on the first call, then hooks[1] on the second call, and so on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Hooks Must Be Called in the Same Order&lt;/strong&gt;&lt;br&gt;
Because React relies on the order of hook calls to match values with the correct state slot, &lt;strong&gt;you must never call hooks conditionally or inside loops&lt;/strong&gt;. Otherwise, the order will be inconsistent between renders, and React won’t know which slot corresponds to which hook, causing bugs or errors.&lt;/p&gt;

&lt;p&gt;Incorrect (don’t do this):&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function MyComponent(props) {
  if (props.show) {
    const [count, setCount] = useState(0); // ❌ Hook inside a condition
  }
}

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Correct:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function MyComponent(props) {
  const [count, setCount] = useState(0); // ✅ Always called
  // You can conditionally use the value later
}
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;React needs this consistent ordering to work properly — think of it like stepping through a list of saved values. If the order changes, React ends up reading or writing to the wrong index.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Internal Flow of Hooks in a Component&lt;/strong&gt;&lt;br&gt;
Imagine a component like this:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Counter() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState('Guest');

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;{name}: {count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Internally, React builds a hook state array something like:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hooks = [0, 'Guest']; // index 0 = count, index 1 = name

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;When you click the button, setCount updates index 0 and triggers a re-render. During the re-render, React reads from the hooks array in the same order to re-apply the useState calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. React Fiber: The Core Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7tjnvzftl7hd24ts6a3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7tjnvzftl7hd24ts6a3.png" alt="React Fiber" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Fiber?
&lt;/h3&gt;

&lt;p&gt;React Fiber is the &lt;strong&gt;engine that powers React&lt;/strong&gt; behind the scenes. Introduced in React 16, Fiber was a complete rewrite of React's internal rendering logic to improve performance, responsiveness, and flexibility.&lt;/p&gt;

&lt;p&gt;Before Fiber, React used a synchronous, blocking update model — which meant large updates could freeze the UI. Fiber changed all that by making rendering &lt;strong&gt;incremental&lt;/strong&gt; and &lt;strong&gt;interruptible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of Fiber like a highly efficient project manager. Instead of doing all tasks at once (which might delay user interactions), it breaks them into smaller chunks and pauses/reorders them based on priority.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Does Fiber Work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fiber breaks down rendering work into units, and schedules them based on priority. This makes React feel faster and more responsive — especially on slow devices or large apps.&lt;/p&gt;

&lt;p&gt;Here’s how Fiber improves the update process:&lt;/p&gt;

&lt;p&gt;Incremental rendering: React doesn’t process the whole component tree in one go. It can pause work and resume it later.&lt;/p&gt;

&lt;p&gt;Interruptible rendering: If a more urgent update (like a user typing) comes in, React can pause current work and handle the urgent update first.&lt;/p&gt;

&lt;p&gt;Smart scheduling: React uses a scheduler that decides what updates to do now, and what can wait (e.g., transitions or animations).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fiber Node&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each React element or component becomes a &lt;strong&gt;Fiber node&lt;/strong&gt; — a JavaScript object with links to related nodes and properties. Imagine it like a tree where each node is a task with connections to siblings, parents, and children.&lt;/p&gt;

&lt;p&gt;Here’s what a simplified Fiber node looks like:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  type: MyComponent,        // Function or DOM type
  child: [childNode],       // First child in the tree
  sibling: [nextSibling],   // Next sibling on the same level
  return: [parentNode],     // Parent fiber
  props: { ... },           // Props passed to the component
  stateNode: DOM or class   // Reference to DOM node or class instance
  alternate: [oldFiber]     // Used for diffing with previous version
}
This forms a linked list/tree structure, allowing React to efficiently walk through and update parts of the UI.

&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;Scheduling and Priorities&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;React assigns each update a priority level, called a lane. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;urgent: typing input, clicks&lt;/li&gt;
&lt;li&gt;default: UI updates&lt;/li&gt;
&lt;li&gt;transition: animations or routes&lt;/li&gt;
&lt;li&gt;idle: low-priority background tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;React uses a loop (like requestIdleCallback) to decide which updates to work on, and can yield (pause) between chunks so it doesn’t block the browser.&lt;/p&gt;

&lt;p&gt;Think of it like juggling — React keeps many tasks in the air, but it knows which ones to catch first based on importance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Commit Phase&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once React finishes building the updated Fiber tree (this is called the render phase), it enters the commit phase, where:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DOM updates are applied (in a batch).&lt;/li&gt;
&lt;li&gt;Effects like useLayoutEffect and useEffect are executed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By separating the render and commit phases, React ensures smooth visual updates and allows powerful features like concurrent rendering, Suspense, and transitions.&lt;/p&gt;

&lt;p&gt;React Fiber is the &lt;strong&gt;heart of modern React&lt;/strong&gt;, enabling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smooth, responsive interfaces&lt;/li&gt;
&lt;li&gt;The ability to pause and resume rendering&lt;/li&gt;
&lt;li&gt;Smarter prioritization of UI tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This internal architecture makes it possible to build complex apps without worrying about performance — React takes care of the heavy lifting behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Diving into React's internals isn’t just for advanced developers — it’s a powerful way to level up your day-to-day React skills. When you understand how React works under the hood — from JSX and component trees to the Fiber architecture and hooks — everything starts to make more sense.&lt;/p&gt;

&lt;p&gt;You begin to write cleaner code, avoid common pitfalls, and debug with confidence because you know why React behaves the way it does. You realize that things like stable hook order, using keys in lists, or why rendering is fast and batched aren’t just “rules” — they’re design decisions based on a deeply thought-out engine.&lt;/p&gt;

&lt;p&gt;React is not just a library — it’s a state machine, a scheduler, and a rendering engine all working in sync to deliver fluid user experiences. And the best part? It gives you a simple, declarative API to work with, so you can focus on your product while it handles the complexity.&lt;/p&gt;

&lt;p&gt;So, the next time something in your app feels "off," or you want to improve performance, remember: React’s inner workings are not a black box.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep Learning , Keep Growing&lt;/strong&gt;&lt;/p&gt;

&lt;/span&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building Dynamic Pagination in React: Server-Side Fetching with Client Components</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Mon, 28 Apr 2025 07:39:54 +0000</pubDate>
      <link>https://forem.com/vishw-patel/building-dynamic-pagination-in-react-server-side-fetching-with-client-components-el5</link>
      <guid>https://forem.com/vishw-patel/building-dynamic-pagination-in-react-server-side-fetching-with-client-components-el5</guid>
      <description>&lt;h2&gt;
  
  
  Building Dynamic Pagination in React: Server-Side Fetching with Client Components
&lt;/h2&gt;

&lt;p&gt;Pagination is a &lt;strong&gt;core feature&lt;/strong&gt; for any application dealing with a large amount of data: product listings, blog posts, user lists, etc.&lt;/p&gt;

&lt;p&gt;Today, we'll explore how to implement &lt;strong&gt;dynamic pagination&lt;/strong&gt; that fetches data from the server &lt;strong&gt;page-by-page&lt;/strong&gt;, while keeping the UI fast and smooth with &lt;strong&gt;React Client Components&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use Dynamic Pagination?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Dynamic pagination&lt;/strong&gt; means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetching &lt;strong&gt;only a subset&lt;/strong&gt; of data (e.g., 10 items at a time) from the server.&lt;/li&gt;
&lt;li&gt;Avoiding loading all data at once (which slows down apps).&lt;/li&gt;
&lt;li&gt;Improving &lt;strong&gt;load times&lt;/strong&gt;, &lt;strong&gt;SEO&lt;/strong&gt;, and &lt;strong&gt;UX&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Reducing &lt;strong&gt;server load&lt;/strong&gt; and &lt;strong&gt;bandwidth consumption&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Perfect for ecommerce stores, blogs, dashboards, admin panels, etc.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  How Pagination Works (At a High Level)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;User visits the page.&lt;/li&gt;
&lt;li&gt;Frontend sends a &lt;strong&gt;request to the server&lt;/strong&gt; with a page number.&lt;/li&gt;
&lt;li&gt;Server &lt;strong&gt;sends back only the relevant items&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Frontend &lt;strong&gt;renders&lt;/strong&gt; them dynamically.&lt;/li&gt;
&lt;li&gt;User can navigate between pages, triggering new fetches.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Setting Up the Backend (Fake API Example)
&lt;/h2&gt;

&lt;p&gt;Your backend route might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;here&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*/&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need &lt;strong&gt;items&lt;/strong&gt; and &lt;strong&gt;total count&lt;/strong&gt; to calculate how many pages there are.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frontend: React Pagination Example
&lt;/h2&gt;

&lt;p&gt;Let's build a dynamic pagination system using &lt;strong&gt;React client components&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create a Pagination Service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// services/itemService.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/items?page=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;limit=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Create a PaginatedList Component
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/PaginatedList.tsx&lt;/span&gt;

&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetchItems&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/services/itemService&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PaginatedList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setItems&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTotal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadItems&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setTotal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;loadItems&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;totalPages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-xl font-bold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Items&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"space-y-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"border p-2 rounded"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex gap-2 mt-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"px-4 py-2 bg-gray-300 rounded"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Previous&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"px-4 py-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Page &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; of &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"px-4 py-2 bg-gray-300 rounded"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Next&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Key Features of This Setup
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Server-Side Fetching&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each page fetches only &lt;strong&gt;needed items&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Saves bandwidth and improves speed.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Client Components&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handles &lt;strong&gt;navigation and user interaction&lt;/strong&gt; instantly.&lt;/li&gt;
&lt;li&gt;Fetches new data only when needed (on page change).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Graceful State Handling&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Disable buttons&lt;/strong&gt; when you reach first or last page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smooth user experience&lt;/strong&gt; without page reloads.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Server-Side vs Client-Side Pagination: When to Use
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo0f5bc8hwovqpekri9b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo0f5bc8hwovqpekri9b.png" alt="Server-Side vs Client-Side Pagination" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Dynamic pagination is an essential building block for &lt;strong&gt;scalable&lt;/strong&gt;, &lt;strong&gt;fast&lt;/strong&gt;, and &lt;strong&gt;user-friendly&lt;/strong&gt; React applications.&lt;/p&gt;

&lt;p&gt;By fetching data page-by-page from the server and rendering them smoothly using client-side components, you keep your app lightweight and your users happy.&lt;/p&gt;

&lt;p&gt;Start simple — but always keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proper &lt;strong&gt;state management&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loading states&lt;/strong&gt; and &lt;strong&gt;error handling&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Optimizing &lt;strong&gt;API efficiency&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pagination isn't just about navigation — it's about performance. 🚀&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Build it right, and your app will scale effortlessly, even when you have &lt;strong&gt;millions of records&lt;/strong&gt;!&lt;/p&gt;




</description>
      <category>react</category>
      <category>webdev</category>
      <category>pagination</category>
      <category>serversidepagination</category>
    </item>
    <item>
      <title>Understanding React Server Components (RSC)</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Fri, 25 Apr 2025 07:58:09 +0000</pubDate>
      <link>https://forem.com/vishw-patel/understanding-react-server-components-rsc-3nlo</link>
      <guid>https://forem.com/vishw-patel/understanding-react-server-components-rsc-3nlo</guid>
      <description>&lt;h2&gt;
  
  
  Understanding React Server Components (RSC): The Future of React Rendering
&lt;/h2&gt;

&lt;p&gt;React Server Components (RSC) mark a fundamental shift in how we build performant React applications. Introduced by the React team, RSC aims to combine the &lt;strong&gt;developer-friendly JSX&lt;/strong&gt; syntax with &lt;strong&gt;server-first rendering principles&lt;/strong&gt; to reduce bundle size, enhance performance, and improve scalability.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are React Server Components?
&lt;/h2&gt;

&lt;p&gt;React Server Components are components that are rendered entirely on the &lt;strong&gt;server&lt;/strong&gt;, and their output is &lt;strong&gt;streamed to the client&lt;/strong&gt; without including any of their code in the final JS bundle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Concepts:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero JavaScript shipped to the client&lt;/strong&gt; for server components&lt;/li&gt;
&lt;li&gt;Can be mixed with traditional client components&lt;/li&gt;
&lt;li&gt;Enable fetching data server-side without useEffect or SWR&lt;/li&gt;
&lt;li&gt;Seamlessly integrated in frameworks like &lt;strong&gt;Next.js App Router&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Client vs Server Components: What’s the Difference?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Client Component&lt;/th&gt;
&lt;th&gt;Server Component&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Runs on&lt;/td&gt;
&lt;td&gt;Browser&lt;/td&gt;
&lt;td&gt;Server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript bundle&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can use hooks&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Only use for promises&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Access to DOM/events&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data fetching&lt;/td&gt;
&lt;td&gt;With effects/libraries&lt;/td&gt;
&lt;td&gt;Native (await syntax)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Example:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Server Component&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductList&lt;/span&gt; &lt;span class="na"&gt;products&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Using RSC in Next.js 14
&lt;/h2&gt;

&lt;p&gt;Next.js 13+ App Router supports RSC out of the box. Files in the &lt;code&gt;app/&lt;/code&gt; directory are server components &lt;strong&gt;by default&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Folder Structure:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/app
  /products
    page.tsx    // Server Component
    Product.tsx // Client Component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make a component run on the client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Add &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Benefits of Server Components
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Minimal JS Bundle Size
&lt;/h2&gt;

&lt;p&gt;Server components don’t get bundled for the client, which means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster load time&lt;/li&gt;
&lt;li&gt;Reduced memory footprint&lt;/li&gt;
&lt;li&gt;Better Lighthouse scores&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Server-Side Data Fetching
&lt;/h2&gt;

&lt;p&gt;No need for SWR or &lt;code&gt;useEffect&lt;/code&gt; for data fetching — you can &lt;code&gt;await&lt;/code&gt; directly in the component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improved Developer Experience
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Clearer separation of client/server logic&lt;/li&gt;
&lt;li&gt;Closer to traditional backend-rendered paradigms&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How Server Components Work Internally
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server renders&lt;/strong&gt; the component tree&lt;/li&gt;
&lt;li&gt;Renders are serialized into a special format&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React client runtime&lt;/strong&gt; hydrates the shell and replaces server output as needed&lt;/li&gt;
&lt;li&gt;Maintains full interactivity via &lt;strong&gt;islands of client components&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Streaming:
&lt;/h2&gt;

&lt;p&gt;Server Components support &lt;strong&gt;streaming rendering&lt;/strong&gt; — which means parts of the UI can be shown as they are ready.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Loading&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductList&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When to Use Server Components
&lt;/h2&gt;

&lt;p&gt;Use Server Components when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don’t need interactivity (e.g., static content, product listings)&lt;/li&gt;
&lt;li&gt;You need fast, secure server-side data fetching&lt;/li&gt;
&lt;li&gt;You want to reduce frontend bundle size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid them for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interactive UI (forms, dropdowns)&lt;/li&gt;
&lt;li&gt;Components that use DOM APIs or event handlers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Composing Server and Client Components
&lt;/h2&gt;

&lt;p&gt;You can freely mix server and client components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductList&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ProductCard&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AddToCart&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; // Client-only
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ProductCard&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ProductList&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes RSC flexible for real-world apps where interactivity is needed only in some areas.&lt;/p&gt;




&lt;h2&gt;
  
  
  Security &amp;amp; Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cannot access browser-only APIs&lt;/li&gt;
&lt;li&gt;Do not support state, effects, or DOM manipulation&lt;/li&gt;
&lt;li&gt;Need careful boundary planning (client/server distinction)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Future of React with RSC
&lt;/h2&gt;

&lt;p&gt;React Server Components are setting the stage for the next era of web development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid rendering&lt;/strong&gt; is the new standard&lt;/li&gt;
&lt;li&gt;Combined with &lt;strong&gt;Edge functions&lt;/strong&gt;, you can get fast, dynamic UIs with low latency&lt;/li&gt;
&lt;li&gt;Expect broader framework support beyond Next.js soon&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;React Server Components are &lt;strong&gt;not a replacement&lt;/strong&gt; for client components — they are a &lt;strong&gt;powerful complement&lt;/strong&gt;. By moving the non-interactive logic to the server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your pages load faster&lt;/li&gt;
&lt;li&gt;Bundle sizes shrink&lt;/li&gt;
&lt;li&gt;Data fetching becomes native&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re working with &lt;strong&gt;Next.js&lt;/strong&gt;, &lt;strong&gt;start using RSC today&lt;/strong&gt;. It’s the direction React is heading.&lt;/p&gt;




</description>
      <category>react</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Scalable React Component Patterns: From Atomic Design to Compound Components</title>
      <dc:creator>Vishw Patel</dc:creator>
      <pubDate>Fri, 25 Apr 2025 07:49:14 +0000</pubDate>
      <link>https://forem.com/vishw-patel/scalable-react-component-patterns-from-atomic-design-to-compound-components-13l7</link>
      <guid>https://forem.com/vishw-patel/scalable-react-component-patterns-from-atomic-design-to-compound-components-13l7</guid>
      <description>&lt;h2&gt;
  
  
  Scalable React Component Patterns: From Atomic Design to Compound Components
&lt;/h2&gt;

&lt;p&gt;As your React app grows, the way you organize and build components becomes critical. Instead of just “breaking things into components,” advanced design patterns help you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Promote reusability&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduce prop drilling&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create highly customizable UIs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoid tech debt&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, we’ll explore key React component patterns that help build &lt;strong&gt;modular, maintainable, and scalable&lt;/strong&gt; frontends.&lt;/p&gt;




&lt;h2&gt;
  
  
  Atomic Design: Structuring Components by Granularity
&lt;/h2&gt;

&lt;p&gt;Atomic Design (coined by Brad Frost) is a methodology that breaks the UI into five stages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atoms&lt;/strong&gt; – Basic building blocks (e.g., Button, Input)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Molecules&lt;/strong&gt; – Groups of atoms (e.g., Input + Label)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organisms&lt;/strong&gt; – Full sections (e.g., Header, Card)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Templates&lt;/strong&gt; – Page-level layouts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pages&lt;/strong&gt; – Complete pages with data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Benefits:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Enforces consistency&lt;/li&gt;
&lt;li&gt;Enables design system reuse&lt;/li&gt;
&lt;li&gt;Scales well with teams and folders&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Compound Components: Components That Work Together
&lt;/h2&gt;

&lt;p&gt;Compound components are a pattern where multiple components share implicit state using React context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Trigger&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Tab 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Trigger&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Trigger&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Tab 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Trigger&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Panel 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Panel 2&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Tabs&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why it works:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Components are &lt;strong&gt;declarative&lt;/strong&gt; and readable&lt;/li&gt;
&lt;li&gt;State is managed internally in &lt;code&gt;Tabs&lt;/code&gt;, shared through context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is used by libraries like &lt;strong&gt;Radix UI&lt;/strong&gt; and &lt;strong&gt;Headless UI&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Controlled vs Uncontrolled Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Controlled:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;State is owned by the parent&lt;/li&gt;
&lt;li&gt;Easier to control programmatically&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Uncontrolled:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;DOM manages the state&lt;/li&gt;
&lt;li&gt;Ideal for quick forms or integrating with non-React libs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use &lt;strong&gt;controlled&lt;/strong&gt; when you need validation, centralized state, or interactivity.&lt;/p&gt;




&lt;h2&gt;
  
  
  Render Props: Component Logic Sharing
&lt;/h2&gt;

&lt;p&gt;Render props is a technique to &lt;strong&gt;share logic&lt;/strong&gt; by passing a function as a child.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MouseTracker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Mouse position: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MouseTracker&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MouseTracker&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPos&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// track mouse...&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;children&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before hooks, this was one of the main ways to reuse logic. Still useful for &lt;strong&gt;fine-grained control&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Headless Components: Logic Without Markup
&lt;/h2&gt;

&lt;p&gt;Headless components (like &lt;code&gt;useCombobox()&lt;/code&gt; from Downshift) expose logic but let &lt;em&gt;you&lt;/em&gt; define the UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getItemProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getMenuProps&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCombobox&lt;/span&gt;&lt;span class="p"&gt;({...});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why it scales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keeps logic and markup separate&lt;/li&gt;
&lt;li&gt;Highly composable&lt;/li&gt;
&lt;li&gt;Works with any design system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Great for building &lt;strong&gt;framework-agnostic, accessible libraries&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Presentational + Container Components
&lt;/h2&gt;

&lt;p&gt;This classic pattern separates &lt;strong&gt;logic&lt;/strong&gt; from &lt;strong&gt;UI&lt;/strong&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  Container:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserContainer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserProfile&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Presentational:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is great when using tools like &lt;strong&gt;Storybook&lt;/strong&gt;, where presentational components can be tested in isolation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contextual Components and Portals
&lt;/h2&gt;

&lt;p&gt;Use React’s context to avoid prop-drilling and manage shared state across compound UIs.&lt;/p&gt;

&lt;p&gt;Portals let you render children outside the parent DOM node — ideal for modals, dropdowns, tooltips:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPortal&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Modal&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combined with context, this enables decoupled, accessible UI patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  Custom Hooks + Refs + Imperative Handles
&lt;/h2&gt;

&lt;p&gt;Custom hooks let you extract and reuse logic cleanly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useToggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setOn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggle&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useImperativeHandle&lt;/code&gt; lets you expose internal component methods to parent refs — useful for forms, sliders, and interactive components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useImperativeHandle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;inputRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When and Where to Use Each Pattern
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Atomic Design&lt;/td&gt;
&lt;td&gt;Design systems, scalable folder structure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compound Components&lt;/td&gt;
&lt;td&gt;Tabs, modals, dropdowns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Render Props&lt;/td&gt;
&lt;td&gt;Custom logic with full control over rendering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Headless Components&lt;/td&gt;
&lt;td&gt;Logic-heavy reusable components&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Container/Presentational&lt;/td&gt;
&lt;td&gt;Separation of concerns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context + Portals&lt;/td&gt;
&lt;td&gt;Shared state across UI layers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Mastering these patterns enables you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build clean, reusable, consistent UI systems&lt;/li&gt;
&lt;li&gt;Collaborate better with designers and teams&lt;/li&gt;
&lt;li&gt;Write more maintainable, readable code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern React is more than JSX — it’s a design system toolkit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick the right pattern for the job, and your components will scale like pros.&lt;/strong&gt; 💪✨&lt;/p&gt;




</description>
      <category>webdev</category>
      <category>react</category>
      <category>design</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
