<?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>DEV Community: Yogesh Chavan</title>
    <description>The latest articles on DEV Community by Yogesh Chavan (@myogeshchavan97).</description>
    <link>https://dev.to/myogeshchavan97</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F361592%2F385c82bb-b96c-4cd6-83a3-ffea25be1d8d.jpeg</url>
      <title>DEV Community: Yogesh Chavan</title>
      <link>https://dev.to/myogeshchavan97</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/myogeshchavan97"/>
    <language>en</language>
    <item>
      <title>I Built The Most Advanced Job Application Tracker</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Sat, 08 Aug 2026 09:14:45 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/i-built-the-most-advanced-job-application-tracker-4ddd</link>
      <guid>https://dev.to/myogeshchavan97/i-built-the-most-advanced-job-application-tracker-4ddd</guid>
      <description>&lt;p&gt;If you're actively applying for jobs, you probably know the struggle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did I already apply to this company?&lt;/li&gt;
&lt;li&gt;Which resume version did I send?&lt;/li&gt;
&lt;li&gt;What salary did I mention when I applied?&lt;/li&gt;
&lt;li&gt;What was the budget mentioned in the job posting?&lt;/li&gt;
&lt;li&gt;When did I apply for this one?&lt;/li&gt;
&lt;li&gt;Which interviews are scheduled this week?&lt;/li&gt;
&lt;li&gt;What were the HR contact details again?&lt;/li&gt;
&lt;li&gt;What exactly were the requirements for this role?&lt;/li&gt;
&lt;li&gt;When is my next interview?&lt;/li&gt;
&lt;li&gt;Where did I even find this posting?&lt;/li&gt;
&lt;li&gt;How many of my applications are actually turning into interviews?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of those is answerable. The problem is that the answers are scattered across a spreadsheet, a notes app, your inbox, and your memory — and reassembling them takes longer than the follow-up you were trying to send.&lt;/p&gt;

&lt;p&gt;Spreadsheets are where most people start, and they hold up until somewhere around application number twelve. After that, searching, filtering, and keeping the thing current becomes its own small job — and a spreadsheet still won't tell you that six applications have been sitting in "Applied" for a month, or whether your last twenty went better than the twenty before them.&lt;/p&gt;

&lt;p&gt;That's why I built &lt;strong&gt;HireLoop&lt;/strong&gt; — an advanced job application tracker meant to reduce the mental load of a job search rather than add to it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live app:&lt;/strong&gt; &lt;a href="https://hireloop.yogeshchavan.dev" rel="noopener noreferrer"&gt;hireloop.yogeshchavan.dev&lt;/a&gt; — free to use, with a demo account if you'd rather look around before signing in.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Check out the application demo video below:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/CwcHxG7-p3Q"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;Check out some preview images of the application&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbck3gd81g0zi4kddblue.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbck3gd81g0zi4kddblue.png" alt="HireLoop1" width="799" height="454"&gt;&lt;/a&gt;&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg3mokwrg5vau7ve0xl0m.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg3mokwrg5vau7ve0xl0m.png" alt="HireLoop2" width="800" height="555"&gt;&lt;/a&gt;&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh97wl6l45fjbivsnsha6.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh97wl6l45fjbivsnsha6.png" alt="HireLoop3" width="800" height="477"&gt;&lt;/a&gt;&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff5q8q3k72qcyheeggkk6.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff5q8q3k72qcyheeggkk6.png" alt="HireLoop5" width="800" height="477"&gt;&lt;/a&gt;&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp49r8pmanioeok08ks3t.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp49r8pmanioeok08ks3t.png" alt="HireLoop6" width="800" height="477"&gt;&lt;/a&gt;&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyxgel3ka1xp4fl6suo59.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyxgel3ka1xp4fl6suo59.png" alt="HireLoop7" width="800" height="476"&gt;&lt;/a&gt;&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbvxtq7lflnhe21ij4cor.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbvxtq7lflnhe21ij4cor.png" alt="HireLoop8" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;With HireLoop you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Track every application in one place — status, dates, salary, source, and links&lt;/li&gt;
&lt;li&gt;See where your search stands at a glance on a dashboard&lt;/li&gt;
&lt;li&gt;Move applications through a Kanban pipeline&lt;/li&gt;
&lt;li&gt;Search, filter, and sort as the list grows&lt;/li&gt;
&lt;li&gt;See interviews and deadlines on a calendar&lt;/li&gt;
&lt;li&gt;Analyse interview rates, offer rates, application trends, and which sources actually work&lt;/li&gt;
&lt;li&gt;Store notes, resume versions, HR contacts, salary details, and job links per application&lt;/li&gt;
&lt;li&gt;Mark the ones that matter as favourites&lt;/li&gt;
&lt;li&gt;Keep it private, behind Google or GitHub sign-in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest of this post is the detail behind those lines.&lt;/p&gt;




&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 16&lt;/strong&gt; (App Router) with &lt;strong&gt;React 19&lt;/strong&gt; and &lt;strong&gt;TypeScript&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS v4&lt;/strong&gt; with &lt;strong&gt;shadcn/ui&lt;/strong&gt; components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neon PostgreSQL&lt;/strong&gt; via &lt;strong&gt;Drizzle ORM&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;better-auth&lt;/strong&gt; for Google and GitHub sign-in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recharts&lt;/strong&gt; for charts, &lt;strong&gt;@dnd-kit&lt;/strong&gt; for the board, &lt;strong&gt;Zod&lt;/strong&gt; for validation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Trying it
&lt;/h2&gt;

&lt;p&gt;The app is live at &lt;a href="https://hireloop.yogeshchavan.dev" rel="noopener noreferrer"&gt;hireloop.yogeshchavan.dev&lt;/a&gt; and free to use. There's also a seeded demo account, so you can look around without signing in at all — hit &lt;strong&gt;Try Demo Account&lt;/strong&gt; on the login page and you'll land in a tracker with sample applications already in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Job hunting is stressful enough on its own. The tools around it should be taking weight off, not adding a maintenance task you feel guilty about skipping.&lt;/p&gt;

&lt;p&gt;HireLoop exists because the interesting part of a job search isn't the list — it's the question of whether what you're doing is working, and that question needs structured data and honest math to answer. If you're in a search right now, the demo at &lt;a href="https://hireloop.yogeshchavan.dev" rel="noopener noreferrer"&gt;hireloop.yogeshchavan.dev&lt;/a&gt; is the fastest way to see whether that framing is useful to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 9+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt; for regular content that I share every day.&lt;/p&gt;




</description>
      <category>react</category>
      <category>nextjs</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Stop Writing Every Job Application Email from Scratch</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Fri, 03 Jul 2026 11:46:26 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/stop-writing-every-job-application-email-from-scratch-2pla</link>
      <guid>https://dev.to/myogeshchavan97/stop-writing-every-job-application-email-from-scratch-2pla</guid>
      <description>&lt;p&gt;If you're actively looking for a job, you've probably experienced this.&lt;/p&gt;

&lt;p&gt;You find a role that matches your skills.&lt;/p&gt;

&lt;p&gt;You update your resume (or at least think about it).&lt;/p&gt;

&lt;p&gt;Then comes the application email.&lt;/p&gt;

&lt;p&gt;You open a blank email and spend the next 10–15 minutes trying to write something that sounds professional, personalized, and different from the last email you sent.&lt;/p&gt;

&lt;p&gt;Now repeat that process for 20, 50, or even 100 job applications.&lt;/p&gt;

&lt;p&gt;It quickly becomes one of the most repetitive parts of job searching.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem With Generic Application Emails
&lt;/h2&gt;

&lt;p&gt;Most applicants eventually fall into one of two patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: Copy and paste the same email
&lt;/h3&gt;

&lt;p&gt;This is the fastest approach, but it usually produces emails that could be sent to any company.&lt;/p&gt;

&lt;p&gt;They rarely mention why you're a good fit for a specific role or how your experience aligns with the job requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 2: Rewrite every email manually
&lt;/h3&gt;

&lt;p&gt;The opposite approach is to carefully tailor every application.&lt;/p&gt;

&lt;p&gt;While this produces better emails, it also consumes a significant amount of time.&lt;/p&gt;

&lt;p&gt;When you're applying to multiple jobs every day, those minutes add up quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personalization Doesn't Have to Be Slow
&lt;/h2&gt;

&lt;p&gt;Most job descriptions follow a similar structure.&lt;/p&gt;

&lt;p&gt;They list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Required skills&lt;/li&gt;
&lt;li&gt;Preferred experience&lt;/li&gt;
&lt;li&gt;Responsibilities&lt;/li&gt;
&lt;li&gt;Location&lt;/li&gt;
&lt;li&gt;Employment type&lt;/li&gt;
&lt;li&gt;Additional requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your resume already contains your experience and skills.&lt;/p&gt;

&lt;p&gt;The real challenge is connecting those two pieces of information in a way that feels relevant to the specific position.&lt;/p&gt;

&lt;p&gt;That's a task AI is well suited for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building ApplyAI
&lt;/h2&gt;

&lt;p&gt;To simplify this process, I built &lt;strong&gt;ApplyAI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The idea was straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload your resume once.&lt;/li&gt;
&lt;li&gt;Paste a LinkedIn job URL or the job description from any job portal.&lt;/li&gt;
&lt;li&gt;Let AI analyze both.&lt;/li&gt;
&lt;li&gt;Generate customized email matching with uploaded resume and job description&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of starting with a blank page every time, the application generates a draft tailored to the role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch Quick Demo Below:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/SX__RL4lCzE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Generates
&lt;/h2&gt;

&lt;p&gt;For each job posting, ApplyAI creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A personalized email subject line&lt;/li&gt;
&lt;li&gt;A tailored job application email&lt;/li&gt;
&lt;li&gt;Skills and experience matched to the job requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The generated email isn't locked.&lt;/p&gt;

&lt;p&gt;You can review it, edit any section, regenerate it if needed, and copy it with a single click.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remembering Important Details
&lt;/h2&gt;

&lt;p&gt;Many recruiters ask applicants to include additional information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current CTC&lt;/li&gt;
&lt;li&gt;Expected CTC&lt;/li&gt;
&lt;li&gt;Notice period&lt;/li&gt;
&lt;li&gt;Availability&lt;/li&gt;
&lt;li&gt;Preferred location&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These requests are easy to overlook when applying to many positions.&lt;/p&gt;

&lt;p&gt;ApplyAI checks the job description and reminds you to include these details whenever they're requested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built for Frequent Job Applications
&lt;/h2&gt;

&lt;p&gt;When you're applying for several positions each week, organization becomes just as important as writing.&lt;/p&gt;

&lt;p&gt;The application keeps a history of previously generated emails, making it easy to revisit or reuse past applications.&lt;/p&gt;

&lt;p&gt;Instead of searching through your inbox or local files, everything stays in one place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy by Design
&lt;/h2&gt;

&lt;p&gt;One of the goals while building ApplyAI was to avoid unnecessary data sharing.&lt;/p&gt;

&lt;p&gt;The application can be self-hosted, allowing your resume and generated emails to remain in your own database.&lt;/p&gt;

&lt;p&gt;Your data stays under your control rather than being stored in someone else's cloud service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting It Up
&lt;/h2&gt;

&lt;p&gt;The project is designed to be simple to run locally.&lt;/p&gt;

&lt;p&gt;The setup takes only a few minutes, and the same application can also be deployed to production if you'd like to host it online.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch Complete Demo Below:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/N2i2ch2JZGE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

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

&lt;p&gt;Writing thoughtful application emails is valuable, but writing the same email dozens of times isn't.&lt;/p&gt;

&lt;p&gt;Automating the repetitive parts lets you spend more time doing the things that actually improve your chances of getting interviews—researching companies, preparing for technical rounds, improving your resume, and practicing interview questions.&lt;/p&gt;

&lt;p&gt;If you're applying to multiple jobs every week, having a tool that generates personalized drafts can save hours while making every application more relevant to the role you're targeting.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://courses.yogeshchavan.dev/personalized-job-emails-using-ai-source-code" rel="noopener noreferrer"&gt;GET THE APPLICATION SOURCE CODE + SETUP VIDEO HERE&lt;/a&gt;
&lt;/h3&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt; for regular content that I share every day.&lt;/p&gt;




</description>
      <category>react</category>
      <category>javascript</category>
      <category>nextjs</category>
      <category>ai</category>
    </item>
    <item>
      <title>Master Redux Toolkit &amp; RTK Query Without Spending Weeks Reading Documentation</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Sun, 28 Jun 2026 06:49:16 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/master-redux-toolkit-rtk-query-without-spending-weeks-reading-documentation-5g6i</link>
      <guid>https://dev.to/myogeshchavan97/master-redux-toolkit-rtk-query-without-spending-weeks-reading-documentation-5g6i</guid>
      <description>&lt;p&gt;If you're a React developer, you've probably reached a point where your application has started becoming difficult to manage.&lt;/p&gt;

&lt;p&gt;As your project grows, you'll eventually need to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Global state management&lt;/li&gt;
&lt;li&gt;API data fetching&lt;/li&gt;
&lt;li&gt;Loading and error states&lt;/li&gt;
&lt;li&gt;Data caching&lt;/li&gt;
&lt;li&gt;Cache invalidation&lt;/li&gt;
&lt;li&gt;Scalable project architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is exactly where &lt;strong&gt;Redux Toolkit&lt;/strong&gt; and &lt;strong&gt;RTK Query&lt;/strong&gt; shine.&lt;/p&gt;

&lt;p&gt;The problem?&lt;/p&gt;

&lt;p&gt;Most developers spend &lt;strong&gt;weeks reading documentation&lt;/strong&gt;, watching random YouTube videos, and still struggle to connect everything together.&lt;/p&gt;

&lt;p&gt;That's why I'm hosting a &lt;strong&gt;live online webinar&lt;/strong&gt; where you'll learn everything by live in a hands-on demo.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foux0d8yrhzdrl8ta7i2h.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foux0d8yrhzdrl8ta7i2h.png" alt="Mastering Redux" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📅 Webinar Details
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Title:&lt;/strong&gt; Mastering Redux Toolkit &amp;amp; RTK Query&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date:&lt;/strong&gt; 28th June 2026 (Sunday)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time:&lt;/strong&gt; 6:00 PM IST&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duration:&lt;/strong&gt; 3 Hours&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mode:&lt;/strong&gt; Live Online (Zoom)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What You'll Learn
&lt;/h2&gt;

&lt;p&gt;We'll start from the basics and gradually move to advanced concepts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redux Fundamentals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;What Redux actually is&lt;/li&gt;
&lt;li&gt;Why Redux exists&lt;/li&gt;
&lt;li&gt;Understanding the Store&lt;/li&gt;
&lt;li&gt;Understanding Actions&lt;/li&gt;
&lt;li&gt;Understanding Reducers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Redux Toolkit
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Creating your first Slice&lt;/li&gt;
&lt;li&gt;Managing application state&lt;/li&gt;
&lt;li&gt;Store configuration&lt;/li&gt;
&lt;li&gt;Writing clean Redux code&lt;/li&gt;
&lt;li&gt;Redux Toolkit best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Async Operations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Working with &lt;code&gt;createAsyncThunk&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Fetching data from APIs&lt;/li&gt;
&lt;li&gt;Handling loading states&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;Success responses&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  RTK Query
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;RTK Query from scratch&lt;/li&gt;
&lt;li&gt;API integration&lt;/li&gt;
&lt;li&gt;Data fetching&lt;/li&gt;
&lt;li&gt;Automatic caching&lt;/li&gt;
&lt;li&gt;Cache invalidation&lt;/li&gt;
&lt;li&gt;Refetching strategies&lt;/li&gt;
&lt;li&gt;Mutations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real-World Project
&lt;/h3&gt;

&lt;p&gt;Together we'll build a complete application that demonstrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State management&lt;/li&gt;
&lt;li&gt;API integration&lt;/li&gt;
&lt;li&gt;CRUD operations&lt;/li&gt;
&lt;li&gt;Production-ready folder structure&lt;/li&gt;
&lt;li&gt;Best practices used in real projects&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Bonus for Every Attendee
&lt;/h2&gt;

&lt;p&gt;Every attendee will receive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RTK Query Cheatsheet&lt;/li&gt;
&lt;li&gt;Complete webinar recording&lt;/li&gt;
&lt;li&gt;Full application source code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Once you register for the webinar, even if you can't attend live, you'll still receive all of the above after the webinar.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Attend This Webinar?
&lt;/h2&gt;

&lt;p&gt;Instead of spending weeks trying to understand Redux from scattered tutorials, you'll learn everything in one structured session.&lt;/p&gt;

&lt;p&gt;Here's what makes this webinar different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn by building a real application&lt;/li&gt;
&lt;li&gt;Beginner-friendly explanations&lt;/li&gt;
&lt;li&gt;Step-by-step implementation&lt;/li&gt;
&lt;li&gt;Real-world examples&lt;/li&gt;
&lt;li&gt;Production-ready best practices&lt;/li&gt;
&lt;li&gt;Live Q&amp;amp;A session&lt;/li&gt;
&lt;li&gt;Get your doubts cleared in real time&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  No Prior Redux Knowledge Required
&lt;/h2&gt;

&lt;p&gt;Never used Redux before?&lt;/p&gt;

&lt;p&gt;No problem.&lt;/p&gt;

&lt;p&gt;We'll start from absolute basics and build everything step by step, making this webinar perfect for beginners.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is This Webinar For You?
&lt;/h2&gt;

&lt;p&gt;This webinar is perfect if you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know React but struggle with state management&lt;/li&gt;
&lt;li&gt;Want to learn Redux Toolkit properly&lt;/li&gt;
&lt;li&gt;Want to master RTK Query&lt;/li&gt;
&lt;li&gt;Want to build scalable React applications&lt;/li&gt;
&lt;li&gt;Need to fetch API data efficiently&lt;/li&gt;
&lt;li&gt;Want to understand caching strategies&lt;/li&gt;
&lt;li&gt;Want to prepare for React interviews&lt;/li&gt;
&lt;li&gt;Want to write cleaner and more maintainable code&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Learn Redux Toolkit &amp;amp; RTK Query?
&lt;/h2&gt;

&lt;p&gt;Many React developers eventually struggle with problems like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prop drilling&lt;/li&gt;
&lt;li&gt;Managing complex application state&lt;/li&gt;
&lt;li&gt;Repeated API requests&lt;/li&gt;
&lt;li&gt;Manual loading and error handling&lt;/li&gt;
&lt;li&gt;Keeping cached data synchronized&lt;/li&gt;
&lt;li&gt;Poor project organization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Redux Toolkit dramatically reduces Redux boilerplate, while RTK Query handles API fetching, caching, synchronization, and invalidation with very little code.&lt;/p&gt;

&lt;p&gt;Together, they help you build modern, scalable React applications much faster.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You'll Walk Away With
&lt;/h2&gt;

&lt;p&gt;By the end of this workshop, you'll be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build scalable React applications&lt;/li&gt;
&lt;li&gt;Manage complex application state confidently&lt;/li&gt;
&lt;li&gt;Fetch API data the modern way&lt;/li&gt;
&lt;li&gt;Implement caching like a professional&lt;/li&gt;
&lt;li&gt;Structure large React projects&lt;/li&gt;
&lt;li&gt;Use Redux Toolkit in production applications&lt;/li&gt;
&lt;li&gt;Build APIs using RTK Query with confidence&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Reserve Your Seat Now
&lt;/h2&gt;

&lt;p&gt;Seats are intentionally limited to keep the session interactive.&lt;/p&gt;

&lt;p&gt;If you've been putting off learning Redux Toolkit and RTK Query, this is your opportunity to master both in just &lt;strong&gt;3 hours&lt;/strong&gt; through practical, hands-on learning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Register now and start building production-ready React applications with confidence.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://courses.yogeshchavan.dev/webinar-mastering-redux-toolkit-and-rtk-query" rel="noopener noreferrer"&gt;REGISTER FOR THE WEBINAR HERE&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt; for regular content that I share every day.&lt;/p&gt;




</description>
      <category>react</category>
      <category>redux</category>
      <category>reduxtoolkit</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>HireHub: Launch Your Own Job Board And Hiring Platform Without Spending Months on Development</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Sat, 20 Jun 2026 09:00:51 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/hirehub-launch-your-own-job-board-platform-without-spending-months-on-development-54g</link>
      <guid>https://dev.to/myogeshchavan97/hirehub-launch-your-own-job-board-platform-without-spending-months-on-development-54g</guid>
      <description>&lt;p&gt;Finding the right talent and helping job seekers discover opportunities shouldn't require building a complex platform from scratch.&lt;/p&gt;

&lt;p&gt;That's exactly why I built &lt;strong&gt;&lt;a href="https://hirehub.yogeshchavan.dev/" rel="noopener noreferrer"&gt;HireHub&lt;/a&gt;&lt;/strong&gt; — a complete, production-ready job board and hiring platform designed for entrepreneurs, startups, recruitment agencies, communities, and businesses looking to launch their own hiring marketplace quickly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I have built many such products, which you can check out on my &lt;a href="https://www.yogeshchavan.dev/#projects" rel="noopener noreferrer"&gt;Portfolio page&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Build a Job Board?
&lt;/h2&gt;

&lt;p&gt;The online recruitment industry continues to grow as companies increasingly rely on digital hiring solutions. Businesses need efficient ways to attract talent, while job seekers expect modern search experiences, streamlined applications, and personalized recommendations.&lt;/p&gt;

&lt;p&gt;Building such a platform from scratch can take months of development, testing, and refinement.&lt;/p&gt;

&lt;p&gt;HireHub eliminates that challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet HireHub
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hirehub.yogeshchavan.dev" rel="noopener noreferrer"&gt;HireHub&lt;/a&gt; is a modern multi-role job board platform that provides dedicated experiences for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Job Seekers&lt;/li&gt;
&lt;li&gt;Employers&lt;/li&gt;
&lt;li&gt;Administrators&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything is designed to deliver a seamless hiring experience from job posting to candidate selection.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn346nr2v7dqpjcqmcd4p.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn346nr2v7dqpjcqmcd4p.png" alt="AI Analyser" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;a href="https://hirehub.yogeshchavan.dev" rel="noopener noreferrer"&gt;Try it out for FREE&lt;/a&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Check out the application demo using the &lt;a href="https://hirehub.yogeshchavan.dev/" rel="noopener noreferrer"&gt;Watch Demo&lt;/a&gt; button in the header&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Features for Job Seekers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Advanced Job Search
&lt;/h3&gt;

&lt;p&gt;Help users find relevant opportunities quickly with powerful filtering options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search by job title&lt;/li&gt;
&lt;li&gt;Filter by location&lt;/li&gt;
&lt;li&gt;Job type - part-time, full-time&lt;/li&gt;
&lt;li&gt;Employment type filters&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  One-Click Applications
&lt;/h3&gt;

&lt;p&gt;Candidates can apply for jobs effortlessly using their profile information, resume, and cover note in a single click.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-Powered Experience
&lt;/h3&gt;

&lt;p&gt;Candidate can upload their resume, and AI will extract all the details from the resume and fill out the application details like personal info, skills, education, experience, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Personalized Dashboard
&lt;/h3&gt;

&lt;p&gt;Job seekers can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Track applications&lt;/li&gt;
&lt;li&gt;Save jobs&lt;/li&gt;
&lt;li&gt;Manage profiles&lt;/li&gt;
&lt;li&gt;Upload resumes&lt;/li&gt;
&lt;li&gt;View application history&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Features for Employers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create and Manage Job Listings
&lt;/h3&gt;

&lt;p&gt;Employers can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Post jobs&lt;/li&gt;
&lt;li&gt;Edit listings&lt;/li&gt;
&lt;li&gt;Close positions&lt;/li&gt;
&lt;li&gt;Track applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Applicant Management
&lt;/h3&gt;

&lt;p&gt;Review and manage candidates through a clean dashboard designed to simplify the hiring process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Company Profiles
&lt;/h3&gt;

&lt;p&gt;Allow organizations to showcase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Company information&lt;/li&gt;
&lt;li&gt;Branding&lt;/li&gt;
&lt;li&gt;Open positions&lt;/li&gt;
&lt;li&gt;Hiring details&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Recruitment Workflow
&lt;/h3&gt;

&lt;p&gt;Streamline hiring operations from job creation to candidate selection.&lt;/p&gt;




&lt;h2&gt;
  
  
  Modern Technology Stack
&lt;/h2&gt;

&lt;p&gt;HireHub is built using modern web technologies to ensure performance, scalability, and maintainability.&lt;/p&gt;

&lt;p&gt;Technologies Used - Next.js 16, Shadcn/UI, Tailwind CSS, PostgreSQL database with Drizzle ORM.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;In-built SEO support&lt;/li&gt;
&lt;li&gt;Fast page loads&lt;/li&gt;
&lt;li&gt;Responsive design&lt;/li&gt;
&lt;li&gt;Mobile-friendly experience&lt;/li&gt;
&lt;li&gt;Modern UI/UX&lt;/li&gt;
&lt;li&gt;Scalable architecture&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Who Can Use HireHub?
&lt;/h2&gt;

&lt;p&gt;HireHub is ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recruitment Agencies&lt;/li&gt;
&lt;li&gt;HR Consultancies&lt;/li&gt;
&lt;li&gt;Startup Founders&lt;/li&gt;
&lt;li&gt;Community Builders&lt;/li&gt;
&lt;li&gt;Niche Job Boards&lt;/li&gt;
&lt;li&gt;Freelance Marketplaces&lt;/li&gt;
&lt;li&gt;Industry-Specific Hiring Platforms&lt;/li&gt;
&lt;li&gt;Educational Institutions&lt;/li&gt;
&lt;li&gt;Corporate Hiring Portals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you're targeting tech jobs, healthcare roles, remote work opportunities, or industry-specific hiring, HireHub provides a solid foundation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Save Months of Development Time
&lt;/h2&gt;

&lt;p&gt;Instead of spending months building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;User management&lt;/li&gt;
&lt;li&gt;Employer dashboards&lt;/li&gt;
&lt;li&gt;Job management systems&lt;/li&gt;
&lt;li&gt;Candidate tracking&lt;/li&gt;
&lt;li&gt;Admin panels&lt;/li&gt;
&lt;li&gt;Search functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can launch with a proven platform and focus on growing your business.&lt;/p&gt;




&lt;h2&gt;
  
  
  Customization Available
&lt;/h2&gt;

&lt;p&gt;Need additional features?&lt;/p&gt;

&lt;p&gt;The platform can be customized to fit your specific business requirements, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom branding&lt;/li&gt;
&lt;li&gt;Additional user roles&lt;/li&gt;
&lt;li&gt;Payment integrations&lt;/li&gt;
&lt;li&gt;Subscription plans&lt;/li&gt;
&lt;li&gt;Premium job listings&lt;/li&gt;
&lt;li&gt;Advanced analytics&lt;/li&gt;
&lt;li&gt;Custom workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Ready to Launch Your Own Job Board?
&lt;/h2&gt;

&lt;p&gt;HireHub gives you everything you need to launch a professional hiring platform quickly and efficiently.&lt;/p&gt;

&lt;p&gt;Whether you're building a niche recruitment marketplace, a startup hiring portal, or a large-scale job board, HireHub provides the foundation to get started immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Demo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://hirehub.yogeshchavan.dev" rel="noopener noreferrer"&gt;https://hirehub.yogeshchavan.dev&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Interested in Purchasing or Customizing HireHub?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.yogeshchavan.dev/" rel="noopener noreferrer"&gt;Get in touch&lt;/a&gt; to discuss customization and feature requirements.&lt;/p&gt;

&lt;p&gt;Launch faster. Hire smarter. Grow your recruitment business with HireHub.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt; for regular content that I share every day.&lt;/p&gt;




</description>
      <category>nextjs</category>
      <category>react</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Cypress Testing: Complete Beginner's Guide</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Sat, 06 Jun 2026 06:51:34 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/cypress-testing-complete-beginners-guide-jp9</link>
      <guid>https://dev.to/myogeshchavan97/cypress-testing-complete-beginners-guide-jp9</guid>
      <description>&lt;h2&gt;
  
  
  Section 1: Getting Started with Cypress
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Installing and Setting Up Cypress
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;p&gt;Before installing Cypress, ensure you have Node.js installed on your machine. Cypress requires Node.js 18.x or 20.x and above. You should also have an existing React project or create a new one.&lt;/p&gt;

&lt;p&gt;Check your Node.js version by running this command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# Should output v18.x.x or higher&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Creating a React Project (Optional)
&lt;/h4&gt;

&lt;p&gt;If you don't have an existing React project, create one using Vite which is the recommended approach for new React projects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest my-react-app &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react
&lt;span class="nb"&gt;cd &lt;/span&gt;my-react-app
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Installing Cypress
&lt;/h4&gt;

&lt;p&gt;Navigate to your React project directory and install Cypress as a development dependency. Cypress is a fairly large package, so the installation might take a minute or two:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;cypress &lt;span class="nt"&gt;--save-dev&lt;/span&gt;

&lt;span class="c"&gt;# Or using yarn&lt;/span&gt;
yarn add cypress &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Opening Cypress for the First Time
&lt;/h4&gt;

&lt;p&gt;After installation, open Cypress for the first time. This will create the initial folder structure and configuration files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cypress open
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When Cypress opens for the first time, you'll see a welcome screen where you can choose between E2E Testing and Component Testing. Select &lt;strong&gt;E2E Testing&lt;/strong&gt; to get started with end-to-end tests.&lt;/p&gt;

&lt;p&gt;Cypress will then prompt you to choose a browser. You can select Chrome, Firefox, Edge, or Electron. Choose your preferred browser and click &lt;strong&gt;Start E2E Testing in [Browser]&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Adding NPM Scripts
&lt;/h4&gt;

&lt;p&gt;Add convenient scripts to your &lt;code&gt;package.json&lt;/code&gt; for running Cypress tests:&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;"scripts"&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="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cy:open"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cypress open"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cy:run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cypress run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test:e2e"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"start-server-and-test dev http://localhost:5173 cy:run"&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;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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Use &lt;code&gt;npm run cy:open&lt;/code&gt; for interactive development with the Cypress Test Runner. Use &lt;code&gt;npm run cy:run&lt;/code&gt; for headless execution in CI/CD pipelines.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  2. Understanding Cypress Project Structure
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Project Directory Overview
&lt;/h4&gt;

&lt;p&gt;After initializing Cypress, you'll notice several new folders and files in your project. Understanding each directory and file is essential for organizing your tests effectively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-react-app/
├── cypress/
│   ├── downloads/
│   ├── e2e/
│   │   └── spec.cy.js
│   ├── fixtures/
│   │   └── example.json
│   └── support/
│       ├── commands.js
│       └── e2e.js
├── cypress.config.js
├── package.json
└── src/
    └── (your React app)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Key Directories and Files
&lt;/h4&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;cypress/e2e/&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This is where your test files live. Each test file should have the &lt;code&gt;.cy.js&lt;/code&gt; extension (or &lt;code&gt;.cy.ts&lt;/code&gt; for TypeScript). Cypress will automatically discover and run all test files in this directory.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;cypress/fixtures/&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Fixtures are used to store static test data, typically in JSON format. You can use fixtures to mock API responses or provide consistent test data across multiple tests.&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;cypress/fixtures/user.json&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;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&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;h4&gt;
  
  
  &lt;code&gt;cypress/support/commands.js&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This file is where you define custom Cypress commands. Custom commands help you create reusable test logic that can be shared across multiple test files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// cypress/support/commands.js&lt;/span&gt;

&lt;span class="c1"&gt;// Custom command to login&lt;/span&gt;
&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;login&lt;/span&gt;&lt;span class="dl"&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;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;cy&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-testid="email"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;cy&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-testid="password"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;cy&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-testid="submit"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&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;h4&gt;
  
  
  &lt;code&gt;cypress.config.js&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;This is the main configuration file for Cypress. Here you can set the base URL, viewport dimensions, timeouts, and many other options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// cypress.config.js&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;defineConfig&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;cypress&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="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;e2e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:5173&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;viewportWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;viewportHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;720&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;defaultCommandTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;setupNodeEvents&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;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// implement node event listeners here&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;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Always set a &lt;code&gt;baseUrl&lt;/code&gt; in your &lt;code&gt;cypress.config.js&lt;/code&gt;. This allows you to use &lt;code&gt;cy.visit('/')&lt;/code&gt; instead of &lt;code&gt;cy.visit('http://localhost:5173/')&lt;/code&gt;, making your tests cleaner and easier to maintain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Configuring ESLint for Cypress
&lt;/h4&gt;

&lt;p&gt;When you open Cypress test files in VS Code, you might see ESLint errors like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Error shown in VS Code:&lt;/span&gt;
&lt;span class="c1"&gt;// 'describe' is not defined. eslint(no-undef)&lt;/span&gt;
&lt;span class="c1"&gt;// 'it' is not defined. eslint(no-undef)&lt;/span&gt;
&lt;span class="c1"&gt;// 'cy' is not defined. eslint(no-undef)&lt;/span&gt;
&lt;span class="c1"&gt;// 'beforeEach' is not defined. eslint(no-undef)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This happens because ESLint doesn't know about Cypress global variables. These are not actual errors — your tests will still run. However, to fix these warnings and get proper IntelliSense support, install the Cypress ESLint plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;eslint-plugin-cypress &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update your ESLint configuration file (&lt;code&gt;eslint.config.js&lt;/code&gt;). First, add the import at the top of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cypressPlugin&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;eslint-plugin-cypress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add the following configuration to your ESLint config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;cypress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cypressPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="kd"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recommended&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plugin:cypress/recommended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;reactHooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recommended&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;reactRefresh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;configs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vite&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cypress/globals&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;
  
  
  3. Writing Your First Cypress Test
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Test File Structure
&lt;/h4&gt;

&lt;p&gt;Cypress uses Mocha's BDD syntax for structuring tests. If you've used Jest or Mocha before, you'll feel right at home. Tests are organized using &lt;code&gt;describe&lt;/code&gt; blocks for grouping and &lt;code&gt;it&lt;/code&gt; blocks for individual tests.&lt;/p&gt;

&lt;p&gt;Let's create your first test file. First, here's the React component we'll be testing — a simple Home page component:&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="c1"&gt;// src/pages/Home.jsx&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;Link&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-router-dom&lt;/span&gt;&lt;span class="dl"&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;Home&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="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;"home"&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Welcome to Our App&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is the home page of our application.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;nav&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;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/about"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&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;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/contact"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Contact&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&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;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/counter"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Counter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&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;nav&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Setting Up the App with Routing
&lt;/h4&gt;

&lt;p&gt;To use this Home component, we need to set up React Router in our application. First, install &lt;code&gt;react-router-dom&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react-router-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, set up your &lt;code&gt;App.jsx&lt;/code&gt; with routing to use the Home component:&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="c1"&gt;// src/App.jsx&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;BrowserRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Route&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-router-dom&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="nx"&gt;Home&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;./pages/Home&lt;/span&gt;&lt;span class="dl"&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;App&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="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="nc"&gt;BrowserRouter&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;Routes&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;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="na"&gt;element&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;Home&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;Routes&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;BrowserRouter&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start your development server to run the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;span class="c"&gt;# App will be available at http://localhost:5173&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Writing the Test
&lt;/h4&gt;

&lt;p&gt;Now, create a new file called &lt;code&gt;home.cy.js&lt;/code&gt; in the &lt;code&gt;cypress/e2e&lt;/code&gt; directory to test this component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// cypress/e2e/home.cy.js&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Home Page&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;beforeEach&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="c1"&gt;// Visit the home page before each test&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should display the welcome message&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome to Our App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should have a navigation menu&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;cy&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nav&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;exist&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cy&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nav a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;have.length.at.least&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Code Explanation
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;cy.visit('/')&lt;/code&gt;&lt;/strong&gt; — Navigates to the home page of your application. The &lt;code&gt;'/'&lt;/code&gt; path uses the &lt;code&gt;baseUrl&lt;/code&gt; configured in &lt;code&gt;cypress.config.js&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;cy.contains('Welcome to Our App')&lt;/code&gt;&lt;/strong&gt; — Searches the DOM for an element containing the specified text.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;.should('be.visible')&lt;/code&gt;&lt;/strong&gt; — Asserts that the element is visible on the page. This checks that the element exists, is in the viewport, and is not hidden by CSS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;cy.get('nav')&lt;/code&gt;&lt;/strong&gt; — Selects the &lt;code&gt;nav&lt;/code&gt; element from the DOM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;.should('exist')&lt;/code&gt;&lt;/strong&gt; — Asserts that the element exists in the DOM. Unlike &lt;code&gt;'be.visible'&lt;/code&gt;, this doesn't check if the element is actually visible to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;.should('have.length.at.least', 1)&lt;/code&gt;&lt;/strong&gt; — Asserts that there is at least one matching element (in this case, at least one link inside the nav).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Make sure inside &lt;code&gt;cypress.config.js&lt;/code&gt; file, you have set the &lt;code&gt;baseUrl&lt;/code&gt; to &lt;code&gt;http://localhost:5173&lt;/code&gt; for this test to pass. This allows &lt;code&gt;cy.visit('/')&lt;/code&gt; to navigate to your local development server.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you run &lt;code&gt;npm run cy:open&lt;/code&gt; and select E2E Testing, you'll see the Cypress Test Runner interface. It will display your test files under the &lt;code&gt;cypress/e2e&lt;/code&gt; folder. You should see your &lt;code&gt;home.cy.js&lt;/code&gt; file listed there. Click on it to run the tests.&lt;/p&gt;

&lt;h4&gt;
  
  
  Understanding the Test Structure
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;describe()&lt;/code&gt;&lt;/strong&gt; — Groups related tests together. You can nest describe blocks for better organization. The first argument is a string describing what you're testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;beforeEach()&lt;/code&gt;&lt;/strong&gt; — Runs before each test in the describe block. Perfect for setup tasks like visiting a page or logging in. There's also &lt;code&gt;afterEach()&lt;/code&gt;, &lt;code&gt;before()&lt;/code&gt;, and &lt;code&gt;after()&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;it()&lt;/code&gt;&lt;/strong&gt; — Defines an individual test case. Each &lt;code&gt;it&lt;/code&gt; block should test one specific behavior. The first argument describes what the test should do.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Want the Complete Guide?
&lt;/h2&gt;

&lt;p&gt;This article is an excerpt from my &lt;strong&gt;&lt;a href="https://courses.yogeshchavan.dev/cypress-testing-complete-beginner-s-guide" rel="noopener noreferrer"&gt;Cypress Testing - Complete Beginner's Guide&lt;/a&gt;&lt;/strong&gt;. For the full, in-depth walkthrough — with every concept explained step-by-step and ready-to-use code examples — check out the complete guide.&lt;/p&gt;

&lt;p&gt;Here's everything you'll learn inside:&lt;/p&gt;

&lt;p&gt;→ What is Cypress &amp;amp; why it's replacing Selenium for modern web testing&lt;br&gt;
→ Installing and setting up Cypress from scratch&lt;br&gt;
→ Writing your first Cypress test (step-by-step with a real React app)&lt;br&gt;
→ Selecting elements the right way — so your tests never break randomly&lt;br&gt;
→ Interacting with elements — clicks, typing, dropdowns, file uploads &amp;amp; more&lt;br&gt;
→ Assertions and expectations that actually work (and auto-retry)&lt;br&gt;
→ Working with aliases and handling Cypress's async behavior&lt;br&gt;
→ Testing React components in complete isolation&lt;br&gt;
→ Mocking API calls with &lt;code&gt;cy.intercept()&lt;/code&gt; for fast, reliable tests&lt;br&gt;
→ Testing forms, validation, and real-time user input&lt;br&gt;
→ Testing authentication flows — login, logout &amp;amp; protected routes&lt;br&gt;
→ Best practices used by top engineering teams to keep test suites maintainable&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you found this article helpful, the full guide takes it much further.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want More Such Guides?&lt;/strong&gt; Check out the &lt;a href="https://courses.yogeshchavan.dev/the-ultimate-react-ebooks-components-hooks-redux-routing-and-more" rel="noopener noreferrer"&gt;Ultimate React Ebooks Collection&lt;/a&gt; with 20+ useful and practical guides.&lt;/p&gt;




&lt;h2&gt;
  
  
  Don't Miss This!
&lt;/h2&gt;

&lt;p&gt;Don't miss the &lt;a href="https://courses.yogeshchavan.dev/all-courses-and-ebooks?utm_source=podia&amp;amp;utm_medium=email&amp;amp;utm_campaign=3105808" rel="noopener noreferrer"&gt;&lt;strong&gt;Lifetime/Pro Subscription&lt;/strong&gt;&lt;/a&gt; — get lifetime access to all my 30+ current and all future courses, ebooks, webinars along with &lt;a href="https://courses.yogeshchavan.dev/applications-source-code-bundle?utm_source=podia&amp;amp;utm_medium=email&amp;amp;utm_campaign=3105808" rel="noopener noreferrer"&gt;&lt;strong&gt;Applications Source Code Bundle&lt;/strong&gt;&lt;/a&gt; (Bonus Offer), for just &lt;strong&gt;$10 / ₹850 (95% OFF)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;⚡ &lt;strong&gt;Limited-Time Offer&lt;/strong&gt;&lt;br&gt;
⚡ &lt;strong&gt;One-Time Payment&lt;/strong&gt;&lt;br&gt;
⚡ &lt;strong&gt;Lifetime Access&lt;/strong&gt;&lt;br&gt;
⚡ &lt;strong&gt;All Future Courses/ebooks/webinars Included&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The discount won't stay forever. Grab it while it's available.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt; for regular content that I share every day.&lt;/p&gt;




</description>
      <category>cypress</category>
      <category>testing</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What's hiding behind that link? There's only one way to find out.</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Fri, 05 Jun 2026 08:49:21 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/whats-hiding-behind-that-link-theres-only-one-way-to-find-out-d2h</link>
      <guid>https://dev.to/myogeshchavan97/whats-hiding-behind-that-link-theres-only-one-way-to-find-out-d2h</guid>
      <description>&lt;p&gt;You get a message with a link: &lt;code&gt;https://bit.ly/4xgurWK&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;No context. No preview. Just a short URL pointing somewhere unknown.&lt;/p&gt;

&lt;p&gt;Most people do one of two things — click it and hope for the best, or ignore it entirely. Neither is great. There's a third option, and it's what I built &lt;strong&gt;RevealURL&lt;/strong&gt; for.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem With Short Links
&lt;/h2&gt;

&lt;p&gt;URL shorteners are genuinely useful. They tame long, unwieldy links for sharing on social media, in print, or in messages. &lt;/p&gt;

&lt;p&gt;But they come with a tradeoff: &lt;strong&gt;you can no longer see where you're going before you arrive.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That tradeoff is mostly harmless when you trust the sender. But in practice, short links show up in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Phishing emails that impersonate your bank&lt;/li&gt;
&lt;li&gt;Spam DMs on Twitter/X, Instagram, and WhatsApp&lt;/li&gt;
&lt;li&gt;QR codes on random posters and flyers&lt;/li&gt;
&lt;li&gt;Newsletter footers from lists you barely remember joining&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The link itself tells you nothing. And by the time your browser has loaded it, it's too late — the request has already been made, tracking pixels have fired, and if something was malicious, the damage may already be done.&lt;/p&gt;




&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/dKMv-VBWvlU"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  What RevealURL Does
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://revealurl.yogeshchavan.dev/" rel="noopener noreferrer"&gt;&lt;strong&gt;RevealURL&lt;/strong&gt;&lt;/a&gt; resolves a shortened URL all the way to its final destination — &lt;strong&gt;without ever opening it in your browser.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Paste a link, hit Reveal, and within seconds you'll see:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The final destination URL&lt;/strong&gt; — exactly where the link ends up, after all redirects are followed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The full redirect chain&lt;/strong&gt; — every hop along the way, with its HTTP status code. A well-behaved link usually has one or two hops. Five or more is a red flag worth knowing about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A safety score&lt;/strong&gt; — a heuristic 0–100 rating that checks for things like raw IP addresses, missing HTTPS, suspicious keywords in the URL, look-alike punycode domains, high-abuse TLDs, and unusually deep subdomain structures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A URL breakdown&lt;/strong&gt; — protocol, domain, path, and query parameters laid out clearly so you can read what's actually in the link.&lt;/p&gt;

&lt;p&gt;The key detail: the resolution happens on the server. Your browser never touches the destination. You see the result; the link never sees you.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Quick Example
&lt;/h2&gt;

&lt;p&gt;Take a link like &lt;code&gt;https://bit.ly/4xgurWK&lt;/code&gt;. That's Bitly link shortener, and it wraps nearly every URL posted on the platform. Paste it into RevealURL and you'll see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hop 1: &lt;code&gt;https://bit.ly/4xgurWK&lt;/code&gt; → 301 → the actual destination&lt;/li&gt;
&lt;li&gt;Final URL: &lt;code&gt;https://courses.yogeshchavan.dev/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Safety score: 100 / 100 — Safe&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now imagine that final URL was &lt;code&gt;http://198.51.100.4/login&lt;/code&gt; instead. The score would drop significantly, and you'd see exactly why — raw IP address, no HTTPS, suspicious path. You'd know not to click before clicking.&lt;/p&gt;




&lt;h2&gt;
  
  
  What It Doesn't Do
&lt;/h2&gt;

&lt;p&gt;Worth being clear about what the tool is and isn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's &lt;strong&gt;not a virus scanner&lt;/strong&gt;. It doesn't download or execute anything at the destination — it only inspects HTTP headers and the URL structure itself.&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;doesn't log your queries&lt;/strong&gt;. There's no database, no account system, no tracking. URLs are resolved on demand and the result goes straight to your browser.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Who It's For
&lt;/h2&gt;

&lt;p&gt;If any of these sound familiar, it might be useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You receive links from strangers or automated systems and want a sanity check&lt;/li&gt;
&lt;li&gt;You're curious what's hiding behind a shortened URL before sharing it further&lt;/li&gt;
&lt;li&gt;You're a developer and want to quickly inspect redirect chains without writing a curl one-liner&lt;/li&gt;
&lt;li&gt;You're teaching someone about link safety and want a visual, approachable tool&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://revealurl.yogeshchavan.dev/" rel="noopener noreferrer"&gt;revealurl.yogeshchavan.dev&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No signup. No install. Paste a link, see where it goes.&lt;/p&gt;

&lt;p&gt;The next time someone sends you a sketchy-looking short URL — or even one that looks totally fine — you'll know exactly where it leads before you commit to clicking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Miss This!
&lt;/h2&gt;

&lt;p&gt;Don't miss the &lt;a href="https://courses.yogeshchavan.dev/all-courses-and-ebooks?utm_source=podia&amp;amp;utm_medium=email&amp;amp;utm_campaign=3105808" rel="noopener noreferrer"&gt;&lt;strong&gt;Lifetime/Pro Subscription&lt;/strong&gt;&lt;/a&gt; — get lifetime access to all my 30+ current and all future courses, ebooks, webinars along with &lt;a href="https://courses.yogeshchavan.dev/applications-source-code-bundle?utm_source=podia&amp;amp;utm_medium=email&amp;amp;utm_campaign=3105808" rel="noopener noreferrer"&gt;&lt;strong&gt;Applications Source Code Bundle&lt;/strong&gt;&lt;/a&gt; (Bonus Offer), for just &lt;strong&gt;$10 / ₹850 (95% OFF)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;⚡ &lt;strong&gt;Limited-Time Offer&lt;/strong&gt;&lt;br&gt;
⚡ &lt;strong&gt;One-Time Payment&lt;/strong&gt;&lt;br&gt;
⚡ &lt;strong&gt;Lifetime Access&lt;/strong&gt;&lt;br&gt;
⚡ &lt;strong&gt;All Future Courses/ebooks/webinars Included&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The discount won't stay forever. Grab it while it's available.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt; for regular content that I share every day.&lt;/p&gt;




</description>
      <category>ai</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>I Built an App That Puts You Anywhere in the World — Without Leaving Your Room</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Wed, 03 Jun 2026 07:26:13 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/i-built-an-app-that-puts-you-anywhere-in-the-world-without-leaving-your-room-20he</link>
      <guid>https://dev.to/myogeshchavan97/i-built-an-app-that-puts-you-anywhere-in-the-world-without-leaving-your-room-20he</guid>
      <description>&lt;p&gt;A few months ago, I needed a fresh set of professional photos for my online presence. The kind of shots where you're standing in front of the Eiffel Tower looking effortlessly cool, or walking down a street in Tokyo with the perfect golden-hour light behind you.&lt;/p&gt;

&lt;p&gt;The problem? A professional photoshoot costs $500+, takes weeks to schedule, and requires you to actually be at that location. And if you're a freelancer or creator on a budget, that math just doesn't work.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://frame.yogeshchavan.dev/" rel="noopener noreferrer"&gt;Frame&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea is simple
&lt;/h2&gt;

&lt;p&gt;You upload a few selfies. You pick a destination — Paris, Bali, the Sahara, a quiet street in Santorini, literally anywhere. Frame then generates a full gallery of studio-quality portraits of &lt;em&gt;you&lt;/em&gt;, in that location, with natural poses and DSLR-level aesthetics.&lt;/p&gt;

&lt;p&gt;Your face stays perfectly recognizable in every shot. That was the non-negotiable part for me. What's the point of AI-generated photos if they don't actually look like you?&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The whole process takes about a minute:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Upload 1–10 clear photos of yourself&lt;/strong&gt; — different angles help, skip the sunglasses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search for any location on earth&lt;/strong&gt; — landmarks, beaches, cities, deserts. There are 40+ popular destinations ready to go, or you can type in anything you can imagine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tweak if you want&lt;/strong&gt; — lighting, mood, camera angle, aspect ratio. Or just let the defaults handle it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate&lt;/strong&gt; — you get a full gallery of varied poses: walking, candid, side profile, looking away. No stiff stock-photo energy.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Check out the application demo below.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/a1feC1IROxA"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Who's actually using this
&lt;/h2&gt;

&lt;p&gt;I originally built it for myself, but it turns out a lot of people have the same problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creators&lt;/strong&gt; who need fresh content for social media without doing a full shoot every month.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Founders and professionals&lt;/strong&gt; who want a sharp headshot for LinkedIn or their website but don't want to spend a day at a studio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brand teams&lt;/strong&gt; running product shoots on tight budgets and tighter timelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anyone&lt;/strong&gt; who just wants to see what they'd look like standing on a cliff in Santorini (no judgment — I did this first).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A few things I'm proud of
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Privacy is baked in.&lt;/strong&gt; Your reference photos live only on your account and are deleted immediately once the photoshoot is generated. This wasn't an afterthought — it was a design decision from day one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The prompt guide.&lt;/strong&gt; Not everyone knows how to describe the shot they want. So I built a curated collection of ready-made prompts for iconic spots — Eiffel Tower, Bali Beach, Tokyo streets, and more. Just pick one, copy it, and go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The output quality.&lt;/strong&gt; I spent a lot of time tuning the DSLR aesthetic. The photos don't look AI-generated in the way you'd expect. They look like someone actually hired a photographer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generated Sample Photos
&lt;/h2&gt;

&lt;p&gt;Here are some of the generated sample photos to see it in action.&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%2F6i5cdl67bmb91zm2aevb.webp" 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%2F6i5cdl67bmb91zm2aevb.webp" alt="Generated Image1" width="800" height="1200"&gt;&lt;/a&gt;&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%2F1ow1orwv5k4h5hbwv70g.webp" 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%2F1ow1orwv5k4h5hbwv70g.webp" alt="Generated Image2" width="800" height="1200"&gt;&lt;/a&gt;&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%2Fkccnxhdj4mnam5c9jiaq.webp" 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%2Fkccnxhdj4mnam5c9jiaq.webp" alt="Generated Image3" width="800" height="800"&gt;&lt;/a&gt;&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%2F25pjhonqxcs34i7sx7pm.webp" 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%2F25pjhonqxcs34i7sx7pm.webp" alt="Generated Image4" width="800" height="1200"&gt;&lt;/a&gt;&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%2Fe0ddq0joeea5pjalftou.webp" 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%2Fe0ddq0joeea5pjalftou.webp" alt="Generated Image5" width="800" height="800"&gt;&lt;/a&gt;&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%2F7jvw1txbq4fexvfsasug.webp" 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%2F7jvw1txbq4fexvfsasug.webp" alt="Generated Image6" width="800" height="1200"&gt;&lt;/a&gt;&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%2F7ld7wphhz7misb0zboag.webp" 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%2F7ld7wphhz7misb0zboag.webp" alt="Generated Image7" width="800" height="1200"&gt;&lt;/a&gt;&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%2Fn7w1rwf7lldcll3k2bms.webp" 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%2Fn7w1rwf7lldcll3k2bms.webp" alt="Generated Image8" width="800" height="1200"&gt;&lt;/a&gt;&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%2Fjfoiyz2ink58cm3gxmy4.webp" 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%2Fjfoiyz2ink58cm3gxmy4.webp" alt="Generated Image9" width="800" height="1200"&gt;&lt;/a&gt;&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%2Fgi36fn50dwaq8mnv6ut4.webp" 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%2Fgi36fn50dwaq8mnv6ut4.webp" alt="Generated Image10" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;Frame is live at &lt;a href="https://frame.yogeshchavan.dev/" rel="noopener noreferrer"&gt;frame.yogeshchavan.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's FREE to use.&lt;/p&gt;

&lt;p&gt;Upload a selfie, pick a place, and see what comes back. That's the best way to judge it.&lt;/p&gt;

&lt;p&gt;I'd genuinely love to hear what you think. What locations did you try? What would you want to see added?&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Miss This!
&lt;/h2&gt;

&lt;p&gt;Don't miss the &lt;a href="https://courses.yogeshchavan.dev/all-courses-and-ebooks?utm_source=podia&amp;amp;utm_medium=email&amp;amp;utm_campaign=3105808" rel="noopener noreferrer"&gt;&lt;strong&gt;Lifetime/Pro Subscription&lt;/strong&gt;&lt;/a&gt; — get lifetime access to all my 30+ current and all future courses, ebooks, webinars along with &lt;a href="https://courses.yogeshchavan.dev/applications-source-code-bundle?utm_source=podia&amp;amp;utm_medium=email&amp;amp;utm_campaign=3105808" rel="noopener noreferrer"&gt;&lt;strong&gt;Applications Source Code Bundle&lt;/strong&gt;&lt;/a&gt; (Bonus Offer), for just &lt;strong&gt;$10 / ₹850 (95% OFF)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;⚡ &lt;strong&gt;Limited-Time Offer&lt;/strong&gt;&lt;br&gt;
⚡ &lt;strong&gt;One-Time Payment&lt;/strong&gt;&lt;br&gt;
⚡ &lt;strong&gt;Lifetime Access&lt;/strong&gt;&lt;br&gt;
⚡ &lt;strong&gt;All Future Courses/ebooks/webinars Included&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The discount won't stay forever. Grab it while it's available.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt; for regular content that I share every day.&lt;/p&gt;




</description>
      <category>ai</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Learn MERN Stack by Building and Deploying a Real FullStack Application — Live 2-Day Webinar</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Fri, 22 May 2026 06:55:52 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/learn-mern-stack-by-building-and-deploying-a-real-fullstack-application-live-2-day-webinar-3ljf</link>
      <guid>https://dev.to/myogeshchavan97/learn-mern-stack-by-building-and-deploying-a-real-fullstack-application-live-2-day-webinar-3ljf</guid>
      <description>&lt;p&gt;If you've been putting off learning fullstack development, this weekend is your chance to finally make it happen.&lt;/p&gt;

&lt;p&gt;I'm hosting a &lt;strong&gt;live, hands-on 2-Day MERN Stack Webinar&lt;/strong&gt; where we'll build and deploy a complete fullstack application from scratch — no slides, no fluff, just real code.&lt;/p&gt;




&lt;h2&gt;
  
  
  📅 Dates &amp;amp; Timings
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Day 1&lt;/td&gt;
&lt;td&gt;23rd May (Friday)&lt;/td&gt;
&lt;td&gt;6:00 PM – 9:00 PM IST&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Day 2&lt;/td&gt;
&lt;td&gt;24th May (Saturday)&lt;/td&gt;
&lt;td&gt;6:00 PM – 9:00 PM IST&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Platform:&lt;/strong&gt; Zoom (Live)&lt;br&gt;
&lt;strong&gt;Recording:&lt;/strong&gt; Yes — all registered participants get access to the recording&lt;/p&gt;




&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;By the end of this 2-day webinar, you'll have a &lt;strong&gt;fully deployed fullstack application&lt;/strong&gt; — built with the MERN stack (MongoDB, Express.js, React, Node.js) — running live on the internet.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Day-by-Day Breakdown
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔥 Day 1 — React Fundamentals (Frontend)
&lt;/h3&gt;

&lt;p&gt;We start from the very beginning and build up to a complete React frontend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand the core concepts of React from scratch&lt;/li&gt;
&lt;li&gt;Build UI components the right way&lt;/li&gt;
&lt;li&gt;Manage state and structure your project effectively&lt;/li&gt;
&lt;li&gt;Create a real, working frontend application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No prior React experience required. We'll cover every concept clearly.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔥 Day 2 — Backend + Integration + Deployment
&lt;/h3&gt;

&lt;p&gt;Once the frontend is ready, we build the backend and connect everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn Node.js and Express.js fundamentals&lt;/li&gt;
&lt;li&gt;Build REST APIs from scratch&lt;/li&gt;
&lt;li&gt;Connect your React frontend to the backend&lt;/li&gt;
&lt;li&gt;Deploy the fullstack application to production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the end of Day 2, your app will be live and accessible to anyone on the internet.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Who Is This For?
&lt;/h2&gt;

&lt;p&gt;This webinar is designed for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Beginners&lt;/strong&gt; who want to get started with React&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beginners&lt;/strong&gt; who are just starting with MERN stack development&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developers&lt;/strong&gt; who want hands-on, practical experience over theory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Students&lt;/strong&gt; preparing for real-world projects or job interviews&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anyone&lt;/strong&gt; who wants to understand how frontend and backend connect in a real application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've only worked with one side of the stack — or haven't started at all — this is the right starting point.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Why This Webinar Is Different
&lt;/h2&gt;

&lt;p&gt;Most tutorials teach you concepts. This webinar teaches you by doing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hands-on coding throughout&lt;/strong&gt; — no PowerPoint, no passive watching&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real project&lt;/strong&gt; — something you can add to your portfolio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live session&lt;/strong&gt; — ask questions, get answers in real time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recording included&lt;/strong&gt; — can't attend live? You still get the full recording plus the complete application source code&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚠️ Limited Seats — Register Now
&lt;/h2&gt;

&lt;p&gt;Seats are limited and it's first-come, first-served. If you can't make it live, register anyway — you'll get the recording and the full source code of the application we build.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://courses.yogeshchavan.dev/webinar-build-and-deploy-fullstack-application-using-mern-stack" rel="noopener noreferrer"&gt;Register Here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;If you've been postponing learning fullstack development, this is your sign to start. See you this weekend. 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt; for regular content that I share every day.&lt;/p&gt;




</description>
      <category>react</category>
      <category>node</category>
      <category>mern</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Built a Tool for Turning Customer Reviews Into Shareable Cards — Here's What It Does</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Wed, 20 May 2026 06:31:03 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/i-built-a-tool-for-turning-customer-reviews-into-shareable-cards-heres-what-it-does-1p6g</link>
      <guid>https://dev.to/myogeshchavan97/i-built-a-tool-for-turning-customer-reviews-into-shareable-cards-heres-what-it-does-1p6g</guid>
      <description>&lt;p&gt;Social proof is one of the most persuasive things you can put on a landing page or a social media post. &lt;/p&gt;

&lt;p&gt;But taking a raw review — a chunk of text from an email, a tweet, or a form submission and turning it into something that looks polished enough to actually share is tedious. You're either wrestling with Figma/Canva, or settling for a plain screenshot.&lt;/p&gt;

&lt;p&gt;I got tired of that friction, so I built &lt;a href="https://testimonial-generator.com" rel="noopener noreferrer"&gt;Testimonial Generator&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/koRVbXIb8QE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  What it actually does
&lt;/h2&gt;

&lt;p&gt;At its core, it's a visual editor for testimonial cards. You paste in the review text, the person's name, their role or location, and the card renders live on the right side of the screen as you type. No page reloads, no "click Preview to see changes" — what you see is what you export.&lt;/p&gt;

&lt;p&gt;The output is a crisp PNG or JPG, ready to drop into your website, a slide deck, a newsletter, or a social post.&lt;/p&gt;




&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/ALy9hs2LD7M"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  The customization is real
&lt;/h2&gt;

&lt;p&gt;This isn't a "pick a color" tool. Every element of the card is adjustable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Card style&lt;/strong&gt; — five layout variants: Default, Quote (with big decorative quotation marks), Centered, Bordered (with an accent bar), and Social&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Colors&lt;/strong&gt; — background, text, muted text, border, avatar background — all individually controllable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typography&lt;/strong&gt; — choose your font family&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avatar&lt;/strong&gt; — upload a photo or fall back to auto-generated initials with a colored background&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Star rating&lt;/strong&gt; — show 1–5 stars, or hide them entirely&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tags&lt;/strong&gt; — add a pill label ("Verified", "G2", "AppSumo", whatever fits your context)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Background images&lt;/strong&gt; — upload a background photo with optional transparency and fade overlay&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spacing&lt;/strong&gt; — padding, border radius, shadow size, and card width are all adjustable with sliders&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Border&lt;/strong&gt; — toggle on/off with a custom color&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The live preview reflects every change instantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Presets so you don't start from scratch
&lt;/h2&gt;

&lt;p&gt;There are 14+ built-in presets covering light, dark, quote, centered, and bordered styles. If you find settings you want to reuse — for a specific brand, a specific campaign — you can save your own presets. &lt;/p&gt;




&lt;h2&gt;
  
  
  Collage builder
&lt;/h2&gt;

&lt;p&gt;If you have multiple reviews you want to share at once, the collage builder lets you combine several cards into a single image. Useful for hero sections, social proof carousels, or pitch decks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Collection pages
&lt;/h2&gt;

&lt;p&gt;The part I find most useful for collecting &lt;em&gt;new&lt;/em&gt; testimonials: you can create a public page on a custom slug where customers can submit their own reviews, including photos. &lt;/p&gt;

&lt;p&gt;You give them the link, they fill it out, and the responses come back to your dashboard ready to be turned into cards.&lt;/p&gt;

&lt;p&gt;Free plan gives you one collection page. Pro removes the limit.&lt;/p&gt;




&lt;h2&gt;
  
  
  No account required to start
&lt;/h2&gt;

&lt;p&gt;The generator, collage builder, presets, and export all work without signing in. An account is only needed if you want cloud-synced presets or multiple collection pages.&lt;/p&gt;

&lt;p&gt;Pricing is simple: Free forever, $4/month (billed yearly) for Pro.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it out!
&lt;/h2&gt;

&lt;p&gt;If you collect testimonials from customers, users, or clients and you want a faster way to make them shareable, give it a go: &lt;a href="https://testimonial-generator.com" rel="noopener noreferrer"&gt;testimonial-generator.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No installation, no signup wall. Open it, paste a review, export a card, quickly create public pages to accept feedbacks&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on LinkedIn&lt;/a&gt; for regular content that I share every day.&lt;/p&gt;




</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Beginner's Guide to Docker: From Zero to Hero</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Sat, 16 May 2026 06:49:38 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/beginners-guide-to-docker-from-zero-to-hero-4977</link>
      <guid>https://dev.to/myogeshchavan97/beginners-guide-to-docker-from-zero-to-hero-4977</guid>
      <description>&lt;p&gt;Docker has fundamentally changed how developers build, ship, and run software. If you've ever heard "it works on my machine" — Docker is the fix. This guide walks you through everything you need to get started, from core concepts to writing your first Dockerfile and managing multi-container apps.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Docker?
&lt;/h2&gt;

&lt;p&gt;Docker is an open-source platform that packages applications inside lightweight, isolated environments called &lt;strong&gt;containers&lt;/strong&gt;. A container bundles your code, runtime, system libraries, and configuration into a single portable unit, so an app that runs on your laptop runs identically on a colleague's machine or a production cloud server.&lt;/p&gt;

&lt;p&gt;Released in 2013, Docker builds on long-standing Linux kernel features (namespaces and cgroups) but wraps them in a developer-friendly CLI, a public image registry (Docker Hub), and a declarative file format for building images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use Docker?
&lt;/h3&gt;

&lt;p&gt;Before Docker, deploying apps meant carefully matching server environments, language runtimes, and OS patches. A single mismatch could break production. Docker solves this and brings several other benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt; — the same image runs identically on every machine&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt; — containers start in seconds and use far fewer resources than VMs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation&lt;/strong&gt; — each container has its own filesystem, processes, and network stack&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducibility&lt;/strong&gt; — a Dockerfile is a recipe; anyone can rebuild the exact same image&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservices-friendly&lt;/strong&gt; — small, single-purpose containers compose into larger systems easily&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Massive ecosystem&lt;/strong&gt; — Docker Hub hosts hundreds of thousands of ready-to-use images&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Containers vs. Virtual Machines
&lt;/h3&gt;

&lt;p&gt;Both containers and VMs provide isolation, but they work very differently. A VM includes a full guest OS on top of a hypervisor, while a container shares the host kernel and isolates only the application and its dependencies.&lt;/p&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;Virtual Machine&lt;/th&gt;
&lt;th&gt;Docker Container&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Boot time&lt;/td&gt;
&lt;td&gt;Minutes&lt;/td&gt;
&lt;td&gt;Seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size on disk&lt;/td&gt;
&lt;td&gt;Gigabytes&lt;/td&gt;
&lt;td&gt;Megabytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OS overhead&lt;/td&gt;
&lt;td&gt;Full guest OS&lt;/td&gt;
&lt;td&gt;Shares host kernel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Isolation level&lt;/td&gt;
&lt;td&gt;Hardware-level&lt;/td&gt;
&lt;td&gt;Process-level&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Lower (virtualized)&lt;/td&gt;
&lt;td&gt;Near-native&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Portability&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Containers don't replace VMs in every situation. VMs are still preferable when you need a completely different OS or strict hardware-level isolation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Core Docker Concepts
&lt;/h2&gt;

&lt;p&gt;Five terms come up constantly. Understand these and everything else makes sense.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image&lt;/strong&gt; — a read-only template containing your app and its dependencies. Think of it like a class in OOP — a blueprint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container&lt;/strong&gt; — a running instance of an image. You can run many containers from one image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dockerfile&lt;/strong&gt; — a text file with step-by-step instructions for building an image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registry&lt;/strong&gt; — a server that stores and distributes images. Docker Hub is the default public registry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volume&lt;/strong&gt; — a mechanism for persisting data outside a container's lifecycle.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Docker Works
&lt;/h3&gt;

&lt;p&gt;Docker uses a client-server architecture. When you run &lt;code&gt;docker run nginx&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Docker CLI sends your command to the Docker Daemon (&lt;code&gt;dockerd&lt;/code&gt;) over a REST API.&lt;/li&gt;
&lt;li&gt;The daemon checks if the image exists locally; if not, it pulls it from Docker Hub.&lt;/li&gt;
&lt;li&gt;The daemon creates a container, allocates a writable filesystem layer, attaches networking, and starts the process.&lt;/li&gt;
&lt;li&gt;Output streams back to your terminal.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;On Linux, the daemon talks directly to the kernel. On macOS and Windows, Docker Desktop runs a small Linux VM under the hood — but you barely notice.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Installing Docker
&lt;/h2&gt;

&lt;h3&gt;
  
  
  macOS and Windows
&lt;/h3&gt;

&lt;p&gt;Install &lt;a href="https://www.docker.com/products/docker-desktop" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt; — an all-in-one bundle that includes the daemon, CLI, Docker Compose, and a GUI for managing images and containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linux (Ubuntu/Debian)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update package index&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update

&lt;span class="c"&gt;# Install prerequisites&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;ca-certificates curl gnupg

&lt;span class="c"&gt;# Add Docker's official GPG key&lt;/span&gt;
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 &lt;span class="nt"&gt;-d&lt;/span&gt; /etc/apt/keyrings
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sudo &lt;/span&gt;gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/docker.gpg

&lt;span class="c"&gt;# Add the Docker repository&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
https://download.docker.com/linux/ubuntu jammy stable"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list

&lt;span class="c"&gt;# Install Docker Engine&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;docker-ce docker-ce-cli containerd.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; After installation on Linux, add your user to the &lt;code&gt;docker&lt;/code&gt; group so you don't need &lt;code&gt;sudo&lt;/code&gt; for every command: &lt;code&gt;sudo usermod -aG docker $USER&lt;/code&gt;, then log out and back in.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Verifying the Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# Output: Docker version 25.0.0, build ...&lt;/span&gt;

docker info

&lt;span class="c"&gt;# Run the official hello-world image&lt;/span&gt;
docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;hello-world&lt;/code&gt; image is tiny (a few kilobytes) and prints a friendly message confirming that the daemon, CLI, image pulling, and container execution all work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running Your First Container
&lt;/h3&gt;

&lt;p&gt;Let's run something more interesting — an Nginx web server — in a single command:&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="c"&gt;# Run nginx in the background and map port 8080 -&amp;gt; 80&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 &lt;span class="nt"&gt;--name&lt;/span&gt; my-nginx nginx

&lt;span class="c"&gt;# Open http://localhost:8080 in your browser&lt;/span&gt;
&lt;span class="c"&gt;# When done, clean up&lt;/span&gt;
docker stop my-nginx
docker &lt;span class="nb"&gt;rm &lt;/span&gt;my-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breaking down that command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker run&lt;/code&gt; — create and start a new container from an image&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt; — detached mode; run in the background&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 8080:80&lt;/code&gt; — publish container port 80 to host port 8080&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--name my-nginx&lt;/code&gt; — give the container a friendly name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nginx&lt;/code&gt; — the image to run&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Always give containers explicit names with &lt;code&gt;--name&lt;/code&gt;. Without it, Docker assigns a random name like &lt;code&gt;elated_einstein&lt;/code&gt;, making them harder to manage in scripts.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Docker Images
&lt;/h2&gt;

&lt;p&gt;A Docker image is a read-only, layered filesystem snapshot containing everything needed to run your software: the OS base, language runtime, application code, dependencies, and metadata.&lt;/p&gt;

&lt;p&gt;Images are identified by &lt;code&gt;name:tag&lt;/code&gt; — for example, &lt;code&gt;node:20-alpine&lt;/code&gt; refers to Node.js v20 built on Alpine Linux. If you omit the tag, Docker assumes &lt;code&gt;:latest&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pulling Images from Docker Hub
&lt;/h3&gt;

&lt;p&gt;Docker Hub is the world's largest public registry of container images. You can pull any public image with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull nginx
docker pull nginx:1.25-alpine
docker pull node:20-alpine
docker pull postgres:16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Tags like &lt;code&gt;alpine&lt;/code&gt; mean the image is built on Alpine Linux, which is often under 10 MB. Prefer Alpine variants when image size matters.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Listing and Removing Images
&lt;/h3&gt;

&lt;p&gt;You can see all images stored locally with the following commands:&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="c"&gt;# List all local images&lt;/span&gt;
docker images

&lt;span class="c"&gt;# Remove a single image&lt;/span&gt;
docker rmi nginx:latest

&lt;span class="c"&gt;# Remove all unused images&lt;/span&gt;
docker image prune

&lt;span class="c"&gt;# Remove ALL images (be careful!)&lt;/span&gt;
docker rmi &lt;span class="si"&gt;$(&lt;/span&gt;docker images &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; docker image prune and docker system prune can free a lot of disk space, but they also delete images and containers you might still need. Read the prompt carefully before confirming.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Fixing the "Image Is Being Used" Error
&lt;/h3&gt;

&lt;p&gt;A common error when removing images:&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="nv"&gt;$ &lt;/span&gt;docker rmi nginx:latest

Error response from daemon: conflict: unable to remove repository reference
&lt;span class="s2"&gt;"nginx:latest"&lt;/span&gt; — container eebd38aa4c91 is using its referenced image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a bug. Docker is protecting you: an image cannot be deleted while a container — even a &lt;strong&gt;stopped&lt;/strong&gt; one — still depends on it. The fix is to deal with the container first. You have two options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Remove the container first (recommended)&lt;/strong&gt;&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="c"&gt;# 1. Find the container using the image&lt;/span&gt;
&lt;span class="c"&gt;# Use -a so STOPPED containers show up too&lt;/span&gt;
docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;

&lt;span class="c"&gt;# 2. Remove that container (use -f if it is still running)&lt;/span&gt;
docker &lt;span class="nb"&gt;rm &lt;/span&gt;eebd38aa4c91

&lt;span class="c"&gt;# or by name:&lt;/span&gt;
docker &lt;span class="nb"&gt;rm &lt;/span&gt;my-nginx

&lt;span class="c"&gt;# 3. Now the image deletes cleanly&lt;/span&gt;
docker rmi nginx:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container ID in your error message (here, &lt;code&gt;eebd38aa4c91&lt;/code&gt;) is exactly the one you need to remove in step 2 — Docker tells you which container is the blocker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2: Force-remove the image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The -f (or --force) flag tells Docker to remove the image anyway. It does this by untagging the image — the underlying layers stay on disk as long as the container references them, and are cleaned up once that container is gone.&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="c"&gt;# Force-remove the image reference&lt;/span&gt;
docker rmi &lt;span class="nt"&gt;-f&lt;/span&gt; nginx:latest

&lt;span class="c"&gt;# The container eebd38aa4c91 still exists and still runs,&lt;/span&gt;
&lt;span class="c"&gt;# but the image is now "dangling" (untagged, shown as &amp;lt;none&amp;gt;)&lt;/span&gt;
docker images

&lt;span class="c"&gt;# REPOSITORY TAG    IMAGE ID     SIZE&lt;/span&gt;
&lt;span class="c"&gt;# &amp;lt;none&amp;gt;     &amp;lt;none&amp;gt; 6f8edba05e38 161MB&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Forcing removal does not actually free disk space while a container is still using the image — it only removes the name/tag. Prefer Option 1: remove the container first, then the image. That genuinely reclaims the space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; To clean up everything related to an image in one go: stop and remove all containers created from it, then remove the image. The one-liner docker rm -f $(docker ps -aq --filter ancestor=nginx) removes every container based on the nginx image, after which docker rmi nginx succeeds.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Image Tags and Versions
&lt;/h3&gt;

&lt;p&gt;Common tag patterns you'll see on Docker Hub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;latest&lt;/code&gt; — the most recent stable build &lt;em&gt;(avoid in production)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;20.10.0&lt;/code&gt; — a specific semantic version, fully reproducible&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;20-alpine&lt;/code&gt; — major version on Alpine Linux&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;20-slim&lt;/code&gt; — a slimmer Debian variant&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bullseye&lt;/code&gt; / &lt;code&gt;bookworm&lt;/code&gt; — built on a specific Debian release&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Avoid &lt;code&gt;:latest&lt;/code&gt; in production. It's a moving target — pin to specific versions like &lt;code&gt;node:20.10.0-alpine&lt;/code&gt; for reproducible builds.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Image Layers Explained
&lt;/h3&gt;

&lt;p&gt;Every image is built from a stack of layers. Each instruction in a Dockerfile produces a layer. Layers are cached and shared between images, which is what makes Docker so efficient. If two images both start with the same base layer (&lt;code&gt;FROM node:20-alpine&lt;/code&gt;, for example), they share that layer on disk.&lt;/p&gt;

&lt;p&gt;You can inspect the layers of any image:&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="c"&gt;# Show the history (layers) of an image&lt;/span&gt;

docker &lt;span class="nb"&gt;history &lt;/span&gt;nginx:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The order of instructions in a Dockerfile directly affects layer caching. Place rarely-changing instructions (installing OS packages) before frequently-changing ones (copying source code). We'll cover this in detail in Section 4.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Working with Containers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Starting Containers (docker run)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;docker run&lt;/code&gt; command is the workhorse of the Docker CLI. It creates a new container from an image and starts it. The general syntax is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="o"&gt;[&lt;/span&gt;OPTIONS] IMAGE &lt;span class="o"&gt;[&lt;/span&gt;COMMAND] &lt;span class="o"&gt;[&lt;/span&gt;ARG...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are the options you'll use over and over:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run in the background (detached)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-it&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Interactive + TTY (for shells)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p HOST:CONTAINER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Publish a port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--name NAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Assign a name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-e KEY=VALUE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Set an environment variable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-v HOST:CONTAINER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mount a volume&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--rm&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Auto-remove when the container exits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--network NAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Attach to a specific network&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few realistic examples:&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="c"&gt;# Interactive Ubuntu shell, auto-removed on exit&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; ubuntu:22.04 bash

&lt;span class="c"&gt;# Redis in the background&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 6379:6379 &lt;span class="nt"&gt;--name&lt;/span&gt; cache redis:7-alpine

&lt;span class="c"&gt;# Postgres with a named volume for persistence&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; pgdata:/var/lib/postgresql/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 5432:5432 &lt;span class="se"&gt;\&lt;/span&gt;
  postgres:16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Detached Mode and Naming
&lt;/h3&gt;

&lt;p&gt;By default &lt;code&gt;docker run&lt;/code&gt; attaches your terminal to the container, which is useful for short-lived commands but not for long-running services. Adding &lt;code&gt;-d&lt;/code&gt; runs the container in the background and prints its ID. Combine that with &lt;code&gt;--name&lt;/code&gt; so you can refer to the container by a friendly handle.&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="c"&gt;# Bad: random name, you'll need the ID later&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; nginx

&lt;span class="c"&gt;# Good: predictable name, easy to script&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; web nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stopping, Starting, Restarting
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Gracefully stop a container (sends SIGTERM, then SIGKILL after 10s)&lt;/span&gt;
docker stop web

&lt;span class="c"&gt;# Start a stopped container&lt;/span&gt;
docker start web

&lt;span class="c"&gt;# Restart (stop + start)&lt;/span&gt;
docker restart web

&lt;span class="c"&gt;# Force-kill immediately (sends SIGKILL)&lt;/span&gt;
docker &lt;span class="nb"&gt;kill &lt;/span&gt;web

&lt;span class="c"&gt;# Pause / unpause (freeze the process)&lt;/span&gt;
docker pause web
docker unpause web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;docker stop&lt;/code&gt; is almost always what you want. docker kill is for unresponsive containers — it skips the graceful shutdown signal.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Removing Containers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Remove a stopped container&lt;/span&gt;
docker &lt;span class="nb"&gt;rm &lt;/span&gt;web

&lt;span class="c"&gt;# Force-remove a running container (stop + remove)&lt;/span&gt;
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; web

&lt;span class="c"&gt;# Remove all stopped containers&lt;/span&gt;
docker container prune

&lt;span class="c"&gt;# Remove every container on the system&lt;/span&gt;
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker ps &lt;span class="nt"&gt;-aq&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If you don't need the container after it exits — for example, a one-off CLI tool — add --rm to docker run so cleanup happens automatically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Executing Commands Inside a Container
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;docker exec&lt;/code&gt; command runs an additional process inside an already-running container. The most common use is opening a shell to debug or inspect state:&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="c"&gt;# Open an interactive bash shell inside the "web" container&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; web bash

&lt;span class="c"&gt;# Some minimal images don't have bash -- use sh instead&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; web sh

&lt;span class="c"&gt;# Run a one-off command without a shell&lt;/span&gt;
docker &lt;span class="nb"&gt;exec &lt;/span&gt;web &lt;span class="nb"&gt;ls&lt;/span&gt; /etc/nginx

&lt;span class="c"&gt;# Run a command as a different user&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; root &lt;span class="nt"&gt;-it&lt;/span&gt; web bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Viewing Logs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Print all logs&lt;/span&gt;
docker logs web

&lt;span class="c"&gt;# Follow logs in real time&lt;/span&gt;
docker logs &lt;span class="nt"&gt;-f&lt;/span&gt; web

&lt;span class="c"&gt;# Show the last 100 lines&lt;/span&gt;
docker logs &lt;span class="nt"&gt;--tail&lt;/span&gt; 100 web

&lt;span class="c"&gt;# Show logs with timestamps&lt;/span&gt;
docker logs &lt;span class="nt"&gt;-t&lt;/span&gt; web

&lt;span class="c"&gt;# Show logs from the last 5 minutes&lt;/span&gt;
docker logs &lt;span class="nt"&gt;--since&lt;/span&gt; 5m web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Configure your app to log to &lt;code&gt;stdout&lt;/code&gt;/&lt;code&gt;stderr&lt;/code&gt; instead of writing to files inside the container. This is the 12-factor approach and lets Docker and orchestrators like Kubernetes collect logs centrally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Inspecting Containers
&lt;/h3&gt;

&lt;p&gt;For deep introspection — IP address, mount points, environment, network settings, and more — use docker inspect:&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="c"&gt;# Print full JSON details of a container&lt;/span&gt;
docker inspect web

&lt;span class="c"&gt;# Extract a specific field using a format template&lt;/span&gt;
docker inspect &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'{{ .NetworkSettings.IPAddress }}'&lt;/span&gt; web

&lt;span class="c"&gt;# Get the exit code of a stopped container&lt;/span&gt;
docker inspect &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'{{ .State.ExitCode }}'&lt;/span&gt; web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Writing Dockerfiles
&lt;/h2&gt;

&lt;p&gt;A Dockerfile is a plain text file with instructions Docker follows to build a custom image. Each instruction produces a new layer. Dockerfiles are the foundation of reproducible builds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy of a Dockerfile
&lt;/h2&gt;

&lt;p&gt;Here is a minimal example. We'll dissect every line below:&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="c"&gt;# Use an official Node.js LTS image as the base&lt;/span&gt;
FROM node:20-alpine

&lt;span class="c"&gt;# Set the working directory inside the container&lt;/span&gt;
WORKDIR /app

&lt;span class="c"&gt;# Copy dependency manifests first (better caching)&lt;/span&gt;
COPY package&lt;span class="k"&gt;*&lt;/span&gt;.json ./

&lt;span class="c"&gt;# Install production dependencies&lt;/span&gt;
RUN npm ci &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev

&lt;span class="c"&gt;# Copy the rest of the application source code&lt;/span&gt;
COPY..

&lt;span class="c"&gt;# Document the port the application listens on&lt;/span&gt;
EXPOSE 3000

&lt;span class="c"&gt;# Define environment variables&lt;/span&gt;
ENV &lt;span class="nv"&gt;NODE_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production

&lt;span class="c"&gt;# Default command to run when the container starts&lt;/span&gt;
CMD &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;, &lt;span class="s2"&gt;"server.js"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common Instructions
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Instruction&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;&lt;code&gt;FROM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets the base image — every Dockerfile starts here&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WORKDIR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets the working directory for subsequent instructions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;COPY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Copies files from the build context into the image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RUN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes a command during the build (e.g., installing packages)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ENV&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets an environment variable (persists at runtime)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ARG&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Defines a build-time variable (disappears after the build)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EXPOSE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Documents which port the container listens on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;USER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets the user the container runs as&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CMD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Default command when the container starts (overridable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ENTRYPOINT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fixed executable — combined with CMD for default flags&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;CMD&lt;/code&gt; vs &lt;code&gt;ENTRYPOINT&lt;/code&gt; — use &lt;code&gt;CMD&lt;/code&gt; for default arguments that are easy to override at runtime. Use &lt;code&gt;ENTRYPOINT&lt;/code&gt; when your image is a specific executable. They work well together: &lt;code&gt;ENTRYPOINT&lt;/code&gt; for the binary, &lt;code&gt;CMD&lt;/code&gt; for default flags.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Your First Dockerfile: A Node.js App
&lt;/h3&gt;

&lt;p&gt;Let's containerize a minimal Express app. The project structure 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;my-app/
├── package.json
├── server.js
├── .dockerignore
└── Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1: Create the project&lt;/strong&gt;&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;mkdir &lt;/span&gt;my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Create &lt;code&gt;server.js&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&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;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from inside a Docker container!&lt;/span&gt;&lt;span class="dl"&gt;'&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;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Listening on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Create the &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start from the official Node.js 20 image (Alpine = small)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:20-alpine&lt;/span&gt;

&lt;span class="c"&gt;# Set the working directory inside the container&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy ONLY the dependency manifests first (better caching)&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;

&lt;span class="c"&gt;# Install dependencies inside the container&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev

&lt;span class="c"&gt;# Copy the rest of the application source code&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Document the port the app listens on&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="c"&gt;# The command that runs when the container starts&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "server.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Create &lt;code&gt;.dockerignore&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules
npm-debug.log
.git
.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why exclude &lt;code&gt;.env&lt;/code&gt;?&lt;/strong&gt; Environment variables should be injected at runtime via &lt;code&gt;-e&lt;/code&gt; flags or Docker secrets, not baked into the image. Committing secrets into an image is a serious security risk.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;This article covers only a portion of the 40 pages &lt;a href="https://courses.yogeshchavan.dev/the-ultimate-react-ebooks-components-hooks-redux-routing-and-more" rel="noopener noreferrer"&gt;complete Beginner's Guide to Docker&lt;/a&gt;.&lt;/strong&gt; The full guide goes much deeper — with more examples, real-world walkthroughs, and step-by-step projects across all the sections below:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 1: Introduction to Docker&lt;/strong&gt;&lt;br&gt;
What is Docker? · Why Use Docker? · Containers vs Virtual Machines · Core Docker Concepts · How Docker Works · Installing Docker · Running Your First Container&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 2: Docker Images&lt;/strong&gt;&lt;br&gt;
What Is an Image? · Pulling Images from Docker Hub · Listing and Removing Images · Fixing the "Image Is Being Used" Error · Image Tags and Versions · Searching the Registry · Image Layers Explained&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 3: Working with Containers&lt;/strong&gt;&lt;br&gt;
Starting Containers · Detached Mode and Naming · Listing Containers · Stopping, Starting, Restarting · Removing Containers · Executing Commands Inside a Container · Viewing Logs · Inspecting Containers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 4: Writing Dockerfiles&lt;/strong&gt;&lt;br&gt;
What Is a Dockerfile? · Anatomy of a Dockerfile · Common Instructions Explained · Your First Dockerfile (Node.js App) · Building the Image · Updating Your Code · The Build Cache and Layer Ordering · .dockerignore · Multi-Stage Builds&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 5: Data Persistence with Volumes&lt;/strong&gt;&lt;br&gt;
Why Containers Are Ephemeral · Bind Mounts vs Named Volumes · Creating and Using Volumes · Real-World Example: Postgres Volume&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 6: Docker Networking&lt;/strong&gt;&lt;br&gt;
Default Networks · Creating a User-Defined Bridge · Connecting Containers by Name · Publishing Ports · Inspecting Networks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 7: Docker Compose&lt;/strong&gt;&lt;br&gt;
Why Compose? · Installing Docker Compose · Your First docker-compose.yml · Common Compose Commands · Real Example: Node.js + Postgres + Redis · Environment Variables and .env Files&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section 8: Best Practices &amp;amp; Next Steps&lt;/strong&gt;&lt;br&gt;
Image Size Optimization · Security Tips · Tagging and Versioning Strategy · Where to Go From Here&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://courses.yogeshchavan.dev/the-ultimate-react-ebooks-components-hooks-redux-routing-and-more" rel="noopener noreferrer"&gt;Get the complete guide here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;strong&gt;Also worth reading:&lt;/strong&gt; If you're interested in staying up to date with the React ecosystem, check out &lt;a href="https://dev.to/myogeshchavan97/react-18-a-complete-guide-to-every-new-feature-54e5"&gt;React 18: A Complete Guide to Every New Feature&lt;/a&gt; — a deep dive into everything that changed in React 18.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on Linkedin&lt;/a&gt; for regular content that I share every day.&lt;/strong&gt;&lt;/p&gt;




</description>
      <category>docker</category>
      <category>react</category>
      <category>javascript</category>
      <category>devops</category>
    </item>
    <item>
      <title>React 18: A Complete Guide to Every New Feature</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Mon, 11 May 2026 06:40:40 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/react-18-a-complete-guide-to-every-new-feature-54e5</link>
      <guid>https://dev.to/myogeshchavan97/react-18-a-complete-guide-to-every-new-feature-54e5</guid>
      <description>&lt;p&gt;React 19 is already here.&lt;/p&gt;

&lt;p&gt;But surprisingly, many React developers are still not familiar with the most useful features introduced in React 18.&lt;/p&gt;

&lt;p&gt;That's exactly why I created this guide, to help you clearly understand the powerful features React 18 provides and how they improve real-world React applications.&lt;/p&gt;

&lt;p&gt;React 18 is the most significant release since React 16 introduced Hooks. At its core, React 18 is about one big idea: &lt;strong&gt;concurrent rendering&lt;/strong&gt;, and everything else flows from it. &lt;/p&gt;

&lt;p&gt;This guide walks through every major feature and API introduced in React 18, with practical code examples you can use today.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Concurrent Rendering&lt;/li&gt;
&lt;li&gt;New Root API — createRoot&lt;/li&gt;
&lt;li&gt;Automatic Batching&lt;/li&gt;
&lt;li&gt;startTransition and useTransition&lt;/li&gt;
&lt;li&gt;useDeferredValue&lt;/li&gt;
&lt;li&gt;Suspense Improvements&lt;/li&gt;
&lt;li&gt;useId&lt;/li&gt;
&lt;li&gt;useSyncExternalStore&lt;/li&gt;
&lt;li&gt;useInsertionEffect&lt;/li&gt;
&lt;li&gt;Strict Mode Changes&lt;/li&gt;
&lt;li&gt;React Server Components&lt;/li&gt;
&lt;li&gt;Migration Guide&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Concurrent Rendering
&lt;/h2&gt;

&lt;p&gt;Concurrent Rendering is the flagship feature of React 18, and it changes how React works at a fundamental level. In all previous versions, rendering was &lt;strong&gt;synchronous and uninterruptible&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Once React started rendering a component tree, it had to finish before the browser could do anything else. This could make the UI feel sluggish during expensive updates.&lt;/p&gt;

&lt;p&gt;With Concurrent Rendering, React gains the ability to &lt;strong&gt;pause, resume, and even abandon renders&lt;/strong&gt;. It can yield to the browser event loop mid-render, keeping the UI responsive even during heavy work. Think of it as React learning how to multitask.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blocking vs. Concurrent Rendering
&lt;/h3&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;React 17 (Blocking)&lt;/th&gt;
&lt;th&gt;React 18 (Concurrent)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rendering&lt;/td&gt;
&lt;td&gt;Synchronous, uninterruptible&lt;/td&gt;
&lt;td&gt;Can pause and resume&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update priority&lt;/td&gt;
&lt;td&gt;All updates treated equally&lt;/td&gt;
&lt;td&gt;Urgent vs. non-urgent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UX during heavy work&lt;/td&gt;
&lt;td&gt;Can feel janky&lt;/td&gt;
&lt;td&gt;Stays responsive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opt-in required&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;Yes, via &lt;code&gt;createRoot()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;React 18 builds on the Fiber architecture to assign priorities to different updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High priority:&lt;/strong&gt; User interactions like clicks and keystrokes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normal priority:&lt;/strong&gt; Data-driven re-renders&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low priority:&lt;/strong&gt; Background updates wrapped in &lt;code&gt;startTransition&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a high-priority update arrives while a low-priority render is in progress, React can interrupt the low-priority work, handle the urgent update, then resume where it left off.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Concurrent Rendering is completely opt-in. Existing code using &lt;code&gt;ReactDOM.render()&lt;/code&gt; continues to work in React 18 without any changes. You only get concurrent features after switching to &lt;code&gt;createRoot()&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. New Root API — createRoot
&lt;/h2&gt;

&lt;p&gt;To unlock concurrent features, you need to migrate from &lt;code&gt;ReactDOM.render()&lt;/code&gt; to the new &lt;code&gt;createRoot()&lt;/code&gt; API. The old API still works in React 18, but it triggers a deprecation warning and opts you out of everything new.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before (React 17)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&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-dom&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="nx"&gt;App&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;./App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&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;App&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;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&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="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&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;h3&gt;
  
  
  After (React 18)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRoot&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-dom/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="nx"&gt;App&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;./App&lt;/span&gt;&lt;span class="dl"&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;rootElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&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;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&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;App&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;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&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;The returned &lt;code&gt;root&lt;/code&gt; object also exposes &lt;code&gt;root.unmount()&lt;/code&gt; to tear down the component tree, replacing the old &lt;code&gt;ReactDOM.unmountComponentAtNode()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  hydrateRoot for SSR
&lt;/h3&gt;

&lt;p&gt;If you're using server-side rendering, replace &lt;code&gt;ReactDOM.hydrate()&lt;/code&gt; with &lt;code&gt;hydrateRoot()&lt;/code&gt;:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;hydrateRoot&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-dom/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="nx"&gt;App&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;./App&lt;/span&gt;&lt;span class="dl"&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;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hydrateRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&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="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// You can still call root.render() later to update the tree&lt;/span&gt;
&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="na"&gt;newProp&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; In micro-frontend architectures, you can create multiple independent roots on a single page — each is fully isolated and concurrent.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. Automatic Batching
&lt;/h2&gt;

&lt;p&gt;Batching is when React groups multiple state updates into a single re-render. This has always existed, but until React 17 it only applied inside React event handlers. &lt;/p&gt;

&lt;p&gt;Updates inside &lt;code&gt;setTimeout&lt;/code&gt;, &lt;code&gt;Promise&lt;/code&gt; callbacks, or native event listeners each triggered their own separate re-render.&lt;/p&gt;

&lt;p&gt;React 18 fixes this. Now &lt;strong&gt;all state updates are batched automatically&lt;/strong&gt;, regardless of where they originate.&lt;/p&gt;

&lt;h3&gt;
  
  
  React 17 — Inconsistent Batching
&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;App&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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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;flag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFlag&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="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// ✅ Batched — 1 re-render (inside React event handler)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&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="nf"&gt;setFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&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;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// ❌ NOT batched — 2 separate re-renders in React 17&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleAsync&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&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="c1"&gt;// re-render 1&lt;/span&gt;
      &lt;span class="nf"&gt;setFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&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;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// re-render 2&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&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;/div&gt;



&lt;h3&gt;
  
  
  React 18 — Automatic Batching Everywhere
&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;App&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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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;flag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFlag&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="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// ✅ Batched — 1 re-render&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleAsync&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&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="nf"&gt;setFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&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;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// ✅ Also batched inside fetch/promise callbacks&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&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="c1"&gt;// batched&lt;/span&gt;
    &lt;span class="nf"&gt;setFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// batched — single re-render!&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;
  
  
  Opting Out with flushSync
&lt;/h3&gt;

&lt;p&gt;If you need an update to be applied synchronously (for example, to read a DOM measurement immediately after a state change), use &lt;code&gt;flushSync&lt;/code&gt;:&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="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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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;flushSync&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-dom&lt;/span&gt;&lt;span class="dl"&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;handleClick&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="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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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;flag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFlag&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="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;flushSync&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="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&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="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// DOM is updated here before the next line executes&lt;/span&gt;

  &lt;span class="nf"&gt;flushSync&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="nf"&gt;setFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&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;f&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// Total: 2 re-renders&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Automatic batching is a free performance win. Just upgrading to React 18 with &lt;code&gt;createRoot&lt;/code&gt; gives you this — no code changes required. Use &lt;code&gt;flushSync&lt;/code&gt; only when you specifically need synchronous DOM updates.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. startTransition and useTransition
&lt;/h2&gt;

&lt;p&gt;Some state updates are urgent — typing in a search box must feel instant. But the results list it drives might be expensive to render. Before React 18, both updates had equal priority, making the input feel sluggish.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Transition API&lt;/strong&gt; lets you tell React: &lt;em&gt;this update is non-urgent — keep the UI responsive and get to it when you can.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  startTransition — The Standalone Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;startTransition&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SearchPage&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;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&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="dl"&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;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setResults&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="nx"&gt;handleSearch&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;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;value&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// Urgent: update the input immediately&lt;/span&gt;
    &lt;span class="nf"&gt;setQuery&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="c1"&gt;// Non-urgent: React can interrupt this if the user keeps typing&lt;/span&gt;
    &lt;span class="nf"&gt;startTransition&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;expensiveSearch&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="nf"&gt;setResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filtered&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="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="p"&gt;&amp;gt;&lt;/span&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;query&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;handleSearch&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;ResultsList&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;results&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="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;h3&gt;
  
  
  useTransition — With a Pending State
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;useTransition&lt;/code&gt; hook is the recommended approach because it also gives you &lt;code&gt;isPending&lt;/code&gt; — a boolean you can use to show a loading indicator while the transition is running.&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="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;useTransition&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TabContainer&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;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTransition&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;tab&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTab&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;home&lt;/span&gt;&lt;span class="dl"&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;selectTab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextTab&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="nf"&gt;startTransition&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="nf"&gt;setTab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextTab&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="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="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TabButton&lt;/span&gt; &lt;span class="na"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&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;selectTab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;home&lt;/span&gt;&lt;span class="dl"&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;gt;&lt;/span&gt;
        Home
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TabButton&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;TabButton&lt;/span&gt; &lt;span class="na"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&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;selectTab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&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;gt;&lt;/span&gt;
        Posts (slow)
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TabButton&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;isPending&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Spinner&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="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&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="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isPending&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mf"&gt;0.7&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="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HomePage&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PostsPage&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="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;h3&gt;
  
  
  Real-World Example: Live Search Over a Large List
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&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;useTransition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMemo&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ITEMS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Item &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&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="p"&gt;}));&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;LiveSearch&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;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&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="dl"&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;deferredQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDeferredQuery&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="dl"&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;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTransition&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;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;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;value&lt;/span&gt; &lt;span class="o"&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="nf"&gt;setQuery&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="c1"&gt;// immediate — input stays responsive&lt;/span&gt;

    &lt;span class="nf"&gt;startTransition&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="nf"&gt;setDeferredQuery&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="c1"&gt;// deferred — filters the big list&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;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&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;ITEMS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deferredQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&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;deferredQuery&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;(&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;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;query&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;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Search..."&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;isPending&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Filtering...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&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;filtered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; results&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&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="nt"&gt;ul&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;filtered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&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="mi"&gt;50&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="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="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="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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; You cannot wrap state updates that control an input's &lt;code&gt;value&lt;/code&gt; in a transition. Input values must always be urgent. Only wrap the downstream, results-driven update.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  5. useDeferredValue
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useDeferredValue&lt;/code&gt; is the sibling of &lt;code&gt;useTransition&lt;/code&gt;. While &lt;code&gt;useTransition&lt;/code&gt; wraps the &lt;em&gt;setter&lt;/em&gt;, &lt;code&gt;useDeferredValue&lt;/code&gt; wraps the &lt;em&gt;value itself&lt;/em&gt;. This makes it ideal when you don't control the state update — for example, when a value comes in as a prop.&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="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;useDeferredValue&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&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="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// deferredQuery lags behind query during concurrent renders&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deferredQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDeferredValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// When query !== deferredQuery, a transition is in progress&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isStale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;deferredQuery&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="p"&gt;&amp;gt;&lt;/span&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;query&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setQuery&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;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Dim results while the deferred value catches up */&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="na"&gt;style&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="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isStale&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mf"&gt;0.5&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="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SearchResults&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;deferredQuery&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="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;h3&gt;
  
  
  useTransition vs. useDeferredValue
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;useTransition&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;useDeferredValue&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What it wraps&lt;/td&gt;
&lt;td&gt;The state setter&lt;/td&gt;
&lt;td&gt;The value / prop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;isPending&lt;/code&gt; available&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No (check manually with &lt;code&gt;===&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;When you own the state update&lt;/td&gt;
&lt;td&gt;When value comes from props&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  6. Suspense Improvements
&lt;/h2&gt;

&lt;p&gt;Suspense has existed since React 16.6, but React 18 dramatically expands what it can do. The key improvements are full support in concurrent mode, Suspense on the server via Streaming SSR, and truly composable loading states across an entire page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested Suspense Boundaries
&lt;/h3&gt;

&lt;p&gt;Each &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; boundary is independent. A component deep in the tree can suspend without affecting siblings that are already loaded.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Dashboard&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;(&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="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;HeaderSkeleton&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;Header&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;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;SidebarSkeleton&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;Sidebar&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;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;MainContentSkeleton&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;MainContent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Nested boundaries for fine-grained control */&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;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;ChartSkeleton&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;Chart&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;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;TableSkeleton&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;DataTable&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;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MainContent&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;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;h3&gt;
  
  
  SuspenseList — Coordinating Loading Order
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;SuspenseList&lt;/code&gt; lets you control the &lt;em&gt;order&lt;/em&gt; in which suspended components reveal themselves, preventing a jarring "popcorn" effect.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SuspenseList&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProfilePage&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;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SuspenseList&lt;/span&gt; &lt;span class="na"&gt;revealOrder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"forwards"&lt;/span&gt; &lt;span class="na"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"collapsed"&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="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;AvatarSkeleton&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;ProfileAvatar&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;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;DetailsSkeleton&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;ProfileDetails&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;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;PostsSkeleton&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;ProfilePosts&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;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SuspenseList&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// revealOrder: 'forwards' | 'backwards' | 'together'&lt;/span&gt;
  &lt;span class="c1"&gt;// tail: 'collapsed' (show only next skeleton) | 'hidden'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Streaming SSR
&lt;/h3&gt;

&lt;p&gt;The biggest SSR improvement in React 18 is &lt;strong&gt;HTML streaming&lt;/strong&gt;. Instead of waiting for all data to be ready before sending any HTML, React can stream the page in chunks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The shell HTML is sent immediately so the browser can start rendering&lt;/li&gt;
&lt;li&gt;Suspended sections are streamed in as their data resolves&lt;/li&gt;
&lt;li&gt;Each section hydrates independently — no all-or-nothing hydration&lt;/li&gt;
&lt;li&gt;Users can interact with loaded parts while others are still loading&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Streaming SSR uses &lt;code&gt;renderToPipeableStream&lt;/code&gt; (Node.js) or &lt;code&gt;renderToReadableStream&lt;/code&gt; (Edge/Web Streams). Frameworks like Next.js 13+ handle this automatically.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  7. useId
&lt;/h2&gt;

&lt;p&gt;When building accessible UI, you often need to link a &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; to an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; using a unique &lt;code&gt;id&lt;/code&gt;. Generating these with &lt;code&gt;Math.random()&lt;/code&gt; or a counter works on the client but causes &lt;strong&gt;hydration mismatches&lt;/strong&gt; in SSR because the server and client generate different values. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;useId&lt;/code&gt; solves this by producing stable, collision-free IDs that are consistent across environments.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useId&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="c1"&gt;// ❌ Wrong — breaks SSR hydration&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PasswordField&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;id&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;random&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// different on server vs client!&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;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Password&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&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;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Correct — stable and SSR-safe&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PasswordField&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// e.g. ":r0:", ":r1:", etc.&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;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Password&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&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;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;h3&gt;
  
  
  Deriving Multiple IDs from One Call
&lt;/h3&gt;

&lt;p&gt;For accessible components that need several linked IDs, derive them from a single &lt;code&gt;useId&lt;/code&gt; call with a suffix — this is more efficient than calling &lt;code&gt;useId&lt;/code&gt; multiple times.&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;FormField&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hint&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useId&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;inputId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-input`&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;hintId&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-hint`&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="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputId&lt;/span&gt;&lt;span class="si"&gt;}&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;label&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;label&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;input&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;aria-describedby&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hint&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;hintId&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="si"&gt;}&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;hint&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hintId&lt;/span&gt;&lt;span class="si"&gt;}&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;hint&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;p&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="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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Do not use &lt;code&gt;useId&lt;/code&gt; to generate list keys. Keys should come from your data (e.g. &lt;code&gt;item.id&lt;/code&gt;). &lt;code&gt;useId&lt;/code&gt; is specifically for accessibility attributes like &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;htmlFor&lt;/code&gt;, and &lt;code&gt;aria-*&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  8. useSyncExternalStore
&lt;/h2&gt;

&lt;p&gt;This hook is primarily for &lt;strong&gt;library authors&lt;/strong&gt; building state management solutions (Redux, Zustand, MobX, etc.). It provides a safe, concurrent-mode-compatible way to subscribe to data stores that live outside React.&lt;/p&gt;

&lt;p&gt;The problem it solves is called &lt;strong&gt;tearing&lt;/strong&gt;: in concurrent mode, React can render a component tree partially and then pause. &lt;/p&gt;

&lt;p&gt;If your component reads from an external store at different points during that render, it might see two different values — a visual inconsistency. &lt;code&gt;useSyncExternalStore&lt;/code&gt; prevents this.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSyncExternalStore&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="c1"&gt;// Subscribing to the browser's online/offline status&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useOnlineStatus&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="nf"&gt;useSyncExternalStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// subscribe: called when React needs to resubscribe&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&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="c1"&gt;// getSnapshot: returns the current value (client)&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// getServerSnapshot: value to use during SSR&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;StatusBadge&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;isOnline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useOnlineStatus&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isOnline&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;badge-green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;badge-red&lt;/span&gt;&lt;span class="dl"&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isOnline&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Offline&lt;/span&gt;&lt;span class="dl"&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;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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you use &lt;a href="https://courses.yogeshchavan.dev/getting-started-with-redux-redux-toolkit-and-becoming-pro-2024-edition" rel="noopener noreferrer"&gt;Redux Toolkit&lt;/a&gt;, &lt;a href="https://master-zustand.yogeshchavan.dev/" rel="noopener noreferrer"&gt;Zustand&lt;/a&gt;, or Jotai, they already integrate &lt;code&gt;useSyncExternalStore&lt;/code&gt; internally. You only need this hook when writing your own state management library or React integration.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  9. useInsertionEffect
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useInsertionEffect&lt;/code&gt; is a specialized hook aimed squarely at &lt;strong&gt;CSS-in-JS library authors&lt;/strong&gt;. It fires synchronously before any DOM mutations, which allows CSS rules to be injected into the DOM &lt;em&gt;before&lt;/em&gt; React reads layout in &lt;code&gt;useLayoutEffect&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The execution order is: &lt;code&gt;useInsertionEffect&lt;/code&gt; → &lt;code&gt;useLayoutEffect&lt;/code&gt; → &lt;code&gt;useEffect&lt;/code&gt;.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useInsertionEffect&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="c1"&gt;// Inside a CSS-in-JS library — not your application code&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useCSS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;useInsertionEffect&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isInserted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;insertStyleSheet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getClassName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Unless you are writing a CSS-in-JS library, you should not use &lt;code&gt;useInsertionEffect&lt;/code&gt;. For regular side effects use &lt;code&gt;useEffect&lt;/code&gt;, and for DOM measurements use &lt;code&gt;useLayoutEffect&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  10. Strict Mode Changes
&lt;/h2&gt;

&lt;p&gt;React 18's Strict Mode introduces a new development-only check: it intentionally &lt;strong&gt;mounts, unmounts, and remounts every component&lt;/strong&gt;. This means effects run twice in development:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mount → run effect → cleanup effect → remount → run effect again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simulates a future React feature (the "offscreen" API) where components can be hidden and reshown — like navigating away from and back to a tab. Your effects need to be resilient to this.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Breaks and How to Fix It
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Breaks in Strict Mode — no cleanup, double fetch&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setData&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="c1"&gt;// ✅ Fixed — use AbortController for cleanup&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AbortError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&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;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&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="c1"&gt;// ❌ Breaks — subscribes without unsubscribing&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dataStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Missing cleanup!&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Fixed — always return a cleanup function&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dataStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&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;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If your app behaves oddly in Strict Mode after upgrading to React 18, that's React catching a real bug — missing cleanup in your effects. Fix the cleanup rather than disabling Strict Mode.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  11. React Server Components
&lt;/h2&gt;

&lt;p&gt;React Server Components (RSC) are a new paradigm designed alongside React 18's concurrent architecture. They let you write components that render &lt;strong&gt;exclusively on the server&lt;/strong&gt; and are never sent to the client as JavaScript — meaning zero bundle size impact.&lt;/p&gt;

&lt;p&gt;While RSC require framework support (Next.js App Router being the primary implementation), understanding them is increasingly essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server vs. Client Components at a Glance
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Server Component&lt;/th&gt;
&lt;th&gt;Client Component&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; at component level&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;
&lt;code&gt;useState&lt;/code&gt; / &lt;code&gt;useEffect&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser APIs&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Direct database / filesystem access&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;
&lt;code&gt;onClick&lt;/code&gt; and other event handlers&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bundle size impact&lt;/td&gt;
&lt;td&gt;0 bytes&lt;/td&gt;
&lt;td&gt;Adds to bundle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context API&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Server Component Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// No directive needed — Server Component by default in Next.js App Router&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="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Direct database access — no useEffect, no fetch boilerplate&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;reviews&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&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;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;h1&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;p&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;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&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;p&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Price: $&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;price&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Client Components can be composed inside Server Components */&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;AddToCartButton&lt;/span&gt; &lt;span class="na"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&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;reviews&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;review&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="nc"&gt;ReviewCard&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;review&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;review&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;review&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;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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Client Component Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="c1"&gt;// This directive opts the component into the client bundle&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="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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AddToCartButton&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;productId&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;added&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAdded&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="kc"&gt;false&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;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&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="kc"&gt;false&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;handleAdd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &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="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;addToCart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setAdded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;added&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Added to cart ✓&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;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;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="nx"&gt;handleAdd&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;loading&lt;/span&gt;&lt;span class="si"&gt;}&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;loading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adding...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Add to Cart&lt;/span&gt;&lt;span class="dl"&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;button&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;p&gt;The composition model is powerful: Server Components handle data fetching and heavy lifting, while Client Components handle interactivity. &lt;/p&gt;

&lt;p&gt;The two types compose naturally — Server Components can render Client Components, passing only serializable props across the boundary.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Migration Guide
&lt;/h2&gt;

&lt;p&gt;Migrating from React 17 to React 18 is largely additive. Existing code keeps working, and you can adopt new features incrementally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Update Your Packages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;react@18 react-dom@18

&lt;span class="c"&gt;# TypeScript users&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @types/react@18 @types/react-dom@18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Switch to the New Root API
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&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-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&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="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// After&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;createRoot&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-dom/client&lt;/span&gt;&lt;span class="dl"&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;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Audit Your Effects for Missing Cleanup
&lt;/h3&gt;

&lt;p&gt;With Strict Mode double-invoking effects, any effect that doesn't clean up after itself will surface as a bug. Go through your &lt;code&gt;useEffect&lt;/code&gt; calls and ensure every subscription, timer, and fetch has a corresponding cleanup:&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="c1"&gt;// The correct pattern for every useEffect that starts something&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// always clean up&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dependency&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Adopt New Features Gradually
&lt;/h3&gt;

&lt;p&gt;Once the basics are in place, adopt new features where they make the most impact:&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="c1"&gt;// Free win: automatic batching requires no changes&lt;/span&gt;
&lt;span class="c1"&gt;// Just upgrading + createRoot gives you this&lt;/span&gt;

&lt;span class="c1"&gt;// High impact for search/filter UIs: useTransition&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;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTransition&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;startTransition&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;setResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&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;query&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="c1"&gt;// Useful when value comes from props: useDeferredValue&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deferredQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDeferredValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Accessible forms with SSR: useId&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useId&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;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&amp;lt;/&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  React 18 API Quick Reference
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Type&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;&lt;code&gt;createRoot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Opt in to concurrent features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hydrateRoot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;SSR hydration with concurrent mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useTransition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hook&lt;/td&gt;
&lt;td&gt;Non-urgent state updates with &lt;code&gt;isPending&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;startTransition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Mark updates as non-urgent (no &lt;code&gt;isPending&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useDeferredValue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hook&lt;/td&gt;
&lt;td&gt;Defer re-rendering of non-urgent parts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hook&lt;/td&gt;
&lt;td&gt;Stable, SSR-safe unique IDs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useSyncExternalStore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hook&lt;/td&gt;
&lt;td&gt;Safe subscriptions to external stores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useInsertionEffect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hook&lt;/td&gt;
&lt;td&gt;CSS-in-JS injection (library authors)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;flushSync&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Force synchronous state flush&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automatic Batching&lt;/td&gt;
&lt;td&gt;Behavior&lt;/td&gt;
&lt;td&gt;Fewer re-renders in async contexts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suspense (SSR)&lt;/td&gt;
&lt;td&gt;Feature&lt;/td&gt;
&lt;td&gt;Streaming HTML from the server&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Upgrade to &lt;code&gt;createRoot&lt;/code&gt;&lt;/strong&gt; first — it unlocks every concurrent feature in this guide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic batching&lt;/strong&gt; is a free performance improvement that comes with the upgrade alone.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;&lt;code&gt;useTransition&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;startTransition&lt;/code&gt;&lt;/strong&gt; to keep UIs responsive during expensive updates.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;&lt;code&gt;useDeferredValue&lt;/code&gt;&lt;/strong&gt; when the value driving an expensive render comes from props.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;&lt;code&gt;useId&lt;/code&gt;&lt;/strong&gt; for accessible form relationships in SSR apps, never for list keys.&lt;/li&gt;
&lt;li&gt;If Strict Mode breaks your app after upgrading, &lt;strong&gt;that's a real bug&lt;/strong&gt; — fix the missing cleanup, don't disable Strict Mode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;useSyncExternalStore&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;useInsertionEffect&lt;/code&gt;&lt;/strong&gt; are for library authors; most application developers won't need them directly.&lt;/li&gt;
&lt;li&gt;React Server Components are the future, but they require a supporting framework. If you're on Next.js 13+, explore the App Router.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The common thread across all of React 18 is this: the library is getting smarter about &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;how&lt;/em&gt; it does work, so you can focus on describing &lt;em&gt;what&lt;/em&gt; your UI should look like — and React handles the rest.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;This article content is taken from my &lt;strong&gt;&lt;a href="https://courses.yogeshchavan.dev/the-ultimate-react-ebooks-components-hooks-redux-routing-and-more" rel="noopener noreferrer"&gt;React 18 Features Guide ebook&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you found this guide useful and want to go deeper, check out &lt;strong&gt;&lt;a href="https://courses.yogeshchavan.dev/the-ultimate-react-ebooks-components-hooks-redux-routing-and-more" rel="noopener noreferrer"&gt;The Ultimate React Ebooks Collection&lt;/a&gt;&lt;/strong&gt; — a curated bundle of 20 ebooks and practical guides covering React, Next.js, JavaScript, interview prep, real-world projects, and more. &lt;/p&gt;

&lt;p&gt;Everything you need to go from solid fundamentals to a production-ready React developer, in one place.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.linkedin.com/in/yogesh-chavan97/" rel="noopener noreferrer"&gt;Follow me on Linkedin&lt;/a&gt; for regular content that I share every day.&lt;/strong&gt;&lt;/p&gt;




</description>
      <category>react</category>
      <category>javascript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>I Built An Application For Live Quizzes To Engage Audience With AI Integration</title>
      <dc:creator>Yogesh Chavan</dc:creator>
      <pubDate>Mon, 27 Apr 2026 10:10:29 +0000</pubDate>
      <link>https://dev.to/myogeshchavan97/host-instant-live-ai-quizzes-with-anyone-5fdm</link>
      <guid>https://dev.to/myogeshchavan97/host-instant-live-ai-quizzes-with-anyone-5fdm</guid>
      <description>&lt;p&gt;Whether you're a teacher looking to make learning fun, a trainer running corporate workshops, or someone hosting a party, &lt;a href="https://livequiz.yogeshchavan.dev/" rel="noopener noreferrer"&gt;QuizPulse&lt;/a&gt; makes engagement effortless.&lt;/p&gt;

&lt;p&gt;Ever wanted to run a live quiz for your team, class, or event — but existing tools felt too clunky or too expensive?&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://livequiz.yogeshchavan.dev/" rel="noopener noreferrer"&gt;QuizPulse&lt;/a&gt; to fix exactly that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's what makes it different:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;AI-Generated Questions&lt;/strong&gt;: Describe your topic and AI writes the questions. Upload a PDF, and it generates quiz content automatically. No more hours spent crafting questions from scratch.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Zero Setup for Players&lt;/strong&gt;: Share a 6-digit PIN. Players join instantly from any browser. No downloads, no accounts, no friction.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Real-Time Sync&lt;/strong&gt;: Every player sees the question at the exact same moment. Answers lock in live.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Live Leaderboards&lt;/strong&gt;: Scores update in real-time with smooth animations. The energy stays high and the competition stays fierce. 🏆&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Works Everywhere&lt;/strong&gt;: Phones, tablets, laptops. Any device with a browser.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Perfect for:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🎓 &lt;strong&gt;Classrooms &amp;amp; teachers&lt;/strong&gt;: Test knowledge before training or reinforce learning after each topic&lt;/p&gt;

&lt;p&gt;💼 &lt;strong&gt;Corporate training &amp;amp; workshops&lt;/strong&gt;: Keep employees engaged and measure understanding&lt;/p&gt;

&lt;p&gt;👥 &lt;strong&gt;Team building events&lt;/strong&gt;: Create memorable, interactive experiences&lt;/p&gt;

&lt;p&gt;🎉 &lt;strong&gt;Parties &amp;amp; trivia nights&lt;/strong&gt;: Fun, casual competition for any gathering&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;How it works in 3 steps:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1️⃣ Create a quiz (AI-assisted or manually)&lt;/p&gt;

&lt;p&gt;2️⃣ Share the 6-digit PIN with your audience&lt;/p&gt;

&lt;p&gt;3️⃣ Host the quiz live and watch the leaderboard heat up&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try it free:&lt;/strong&gt; &lt;a href="https://livequiz.yogeshchavan.dev" rel="noopener noreferrer"&gt;livequiz.yogeshchavan.dev&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Check out the short preview below of the application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/oVKr-QS-od4"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/0LHBSk3Wh1U"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Check out some of the application screenshots below.
&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%2Fdameuwx008776fjk7xbd.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%2Fdameuwx008776fjk7xbd.png" alt="AI Questions Generator" width="475" height="538"&gt;&lt;/a&gt;&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%2F9tulwkfph7vghie6ewhj.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%2F9tulwkfph7vghie6ewhj.png" alt="Result" width="680" height="809"&gt;&lt;/a&gt;&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%2Fhu8w219e3m9mrpuy084a.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%2Fhu8w219e3m9mrpuy084a.png" alt="Live Quiz" width="734" height="742"&gt;&lt;/a&gt;&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%2Fl7t2kw7nfu1yl350xlr3.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%2Fl7t2kw7nfu1yl350xlr3.png" alt="Lobby" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why QuizPulse?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Real-Time Sync
&lt;/h3&gt;

&lt;p&gt;Questions appear simultaneously for all players. No lag, no confusion. Everyone sees the same question at the exact same moment, creating that electrifying game-show atmosphere.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-Powered Question Generation
&lt;/h3&gt;

&lt;p&gt;Stop spending hours crafting quiz questions. Simply describe your topic and let AI generate engaging questions instantly. You can even &lt;strong&gt;upload a PDF&lt;/strong&gt; and QuizPulse will extract relevant questions automatically — perfect for turning study materials or training documents into interactive quizzes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero Setup for Players
&lt;/h3&gt;

&lt;p&gt;Players join with a simple 6-digit PIN. That's it. No app downloads, no account creation, no friction. Works on any device with a browser — phones, tablets, laptops.&lt;/p&gt;

&lt;h3&gt;
  
  
  Live Leaderboards
&lt;/h3&gt;

&lt;p&gt;Watch scores update in real-time with smooth animations. Keep the competitive spirit alive as participants race to the top. Nothing motivates like seeing your name climb the rankings.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Create Your Quiz&lt;/strong&gt;&lt;br&gt;
Use AI to generate questions from any topic or PDF, or write your own. Set time limits, customize the experience to fit your needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Share the PIN&lt;/strong&gt;&lt;br&gt;
Launch your quiz and share the 6-digit game PIN. Players simply visit the site and enter the code — they're in within seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Play Live&lt;/strong&gt;&lt;br&gt;
Control the pace, watch real-time results roll in, and celebrate winners together. The energy is contagious.&lt;/p&gt;




&lt;h2&gt;
  
  
  Built for Modern Teams
&lt;/h2&gt;

&lt;p&gt;QuizPulse is built with the latest web technologies for a seamless experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fast &amp;amp; Responsive&lt;/strong&gt;: Works flawlessly on any device&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Beautiful Design&lt;/strong&gt;: A modern, sleek interface that looks professional&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics Dashboard&lt;/strong&gt;: Track participation and quiz performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export Results&lt;/strong&gt;: Download detailed reports of quiz sessions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Get Started in Minutes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sign up for free at &lt;a href="https://livequiz.yogeshchavan.dev" rel="noopener noreferrer"&gt;livequiz.yogeshchavan.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create your first quiz (AI makes it fast)&lt;/li&gt;
&lt;li&gt;Share the PIN with your audience&lt;/li&gt;
&lt;li&gt;Watch engagement soar&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No credit card required. No complicated setup. Just pure, interactive fun.&lt;/p&gt;




&lt;h2&gt;
  
  
  Start Hosting Free Today
&lt;/h2&gt;

&lt;p&gt;Ready to transform your next meeting, class, or event? QuizPulse is free to get started.&lt;/p&gt;

&lt;p&gt;Try it free: &lt;a href="https://livequiz.yogeshchavan.dev" rel="noopener noreferrer"&gt;livequiz.yogeshchavan.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love to hear your feedback! Drop a comment or share with someone who runs quizzes, workshops, or classroom sessions. 🙌&lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I'm a freelancer, &lt;a href="https://www.codementor.io/@myogeshchavan97" rel="noopener noreferrer"&gt;mentor&lt;/a&gt;, and full-stack developer with 12+ years of experience, working primarily with React, Next.js, and Node.js.&lt;/p&gt;

&lt;p&gt;Alongside building real-world web applications, I'm also an Industry/Corporate Trainer, training developers and teams in modern JavaScript, Next.js, and MERN stack technologies with a focus on practical, production-ready skills.&lt;/p&gt;

&lt;p&gt;I've also created &lt;a href="https://courses.yogeshchavan.dev/" rel="noopener noreferrer"&gt;various courses&lt;/a&gt; with 3000+ students enrolled.&lt;/p&gt;

&lt;p&gt;My Portfolio: &lt;a href="https://yogeshchavan.dev/" rel="noopener noreferrer"&gt;https://yogeshchavan.dev/&lt;/a&gt;&lt;/p&gt;




</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
