<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Tapas Adhikary - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Tapas Adhikary - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 10 May 2026 16:27:41 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/atapas/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ The New Definition of Software Engineering in the Age of AI ]]>
                </title>
                <description>
                    <![CDATA[ If you're a software developer today, it's almost impossible to avoid the noise of AI( Artificial Intelligence) and its impact on the industry. You open X or LinkedIn in the morning, and the majority  ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-new-definition-of-software-engineering-in-the-age-of-ai/</link>
                <guid isPermaLink="false">69e79e7ce4367278146642bb</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ llm ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Tue, 21 Apr 2026 15:57:48 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/fdae044d-708e-4a00-93f1-5bcef49097f7.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're a software developer today, it's almost impossible to avoid the noise of AI( Artificial Intelligence) and its impact on the industry. You open X or LinkedIn in the morning, and the majority of the posts you see are the terrifying ones about tech layoffs.</p>
<p>You scroll a little more, and someone is claiming that a new AI tool released last week has already made entry-level developers obsolete. You go to YouTube, and a thumbnail screams that all technologies are dead, all developer jobs are dead, and at the same time, a solo founder claims that they've built a million-dollar full-stack app in five minutes using AI agents.</p>
<p>At some point, you start feeling overwhelmed. You start to question and doubt the nights you've spent learning something, building something. You wonder whether the effort you're putting into mastering a programming language or framework still makes sense. You start asking yourself an extremely uncomfortable question: "<em>Is my career still safe?</em>"</p>
<p>This concern is valid. Instead of dismissing the concern with a lot of motivational talk or toxic positivity, let's do a reality check. The industry is fundamentally changing. Hiring patterns are shifting. Expectations for both junior and senior developers are rising exponentially. And yes, AI is the main catalyst accelerating all these changes.</p>
<p>But there is a massive misunderstanding around what's going on. The narrative that "AI is replacing developers" lacks a lot of details. It has created unnecessary fear because it fails to specify what's actually happening.</p>
<p>Not many devs are coming up to explain these details because a good portion of us are still observing, and some are steering the fear to their individual benefits.</p>
<p>Well, here's my take: AI isn't replacing all software engineers. It's replacing a specific kind of work. The low-level, average, routine execution work is getting replaced with AI much faster than anyone could imagine. As a result, it's forcing us to think of what it means to be a software engineer in today's market.</p>
<p>This article is about that thought process. It's a deep dive into the changing landscape of software development, the shift from effort-based to impact-based engineering, and a practical, actionable roadmap to enable you to remain relevant in the era of AI-assisted coding.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a href="#heading-the-end-of-the-tutorial-driven-era">The End of the Tutorial-Driven Era</a></p>
</li>
<li><p><a href="#heading-lets-decode-the-ai-is-taking-jobs-myth">Let's Decode the "AI is Taking Jobs" Myth</a></p>
</li>
<li><p><a href="#heading-applying-a-clean-architecture">Applying a Clean Architecture</a></p>
</li>
<li><p><a href="#heading-a-practical-ai-era-engineering-roadmap">A Practical, AI-Era Engineering Roadmap</a></p>
<ul>
<li><p><a href="#heading-step-1-strengthen-your-fundamentals">Step 1: Strengthen Your Fundamentals</a></p>
</li>
<li><p><a href="#heading-step-2-build-real-uncomfortable-systems">Step 2: Build Real (Uncomfortable) Systems</a></p>
</li>
<li><p><a href="#heading-step-3-master-the-art-of-debugging">Step 3: Master the Art of Debugging</a></p>
</li>
<li><p><a href="#heading-step-4-use-ai-as-a-tool-not-as-a-crutch">Step 4: Use AI as a Tool, Not as a Crutch</a></p>
</li>
<li><p><a href="#heading-step-5-establishing-a-strong-proof-of-work">Step 5: Establishing a Strong Proof of Work</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-the-must-needed-mindset-shift">The Must-Needed Mindset Shift</a></p>
</li>
<li><p><a href="#heading-if-youve-read-this-far">If You've Read This Far...</a></p>
</li>
</ol>
<h2 id="heading-the-end-of-the-tutorial-driven-era">The End of the Tutorial-Driven Era</h2>
<p>Let's step back for a moment and look at how most of us learned to develop software over the last decade or so.</p>
<p>Between 2010 and 2023, the industry was filled with tutorial-driven developers. We learned to build software by following step-by-step instructions.</p>
<p>Applications like TODO Apps, Weather dashboards, or clones of YouTube or Spotify were in high demand among developers. These projects gave us confidence. They helped us memorise syntax, learn how to use libraries, and figure out how to write a basic frontend and backend.</p>
<p>For a long time, this was enough. The goal was simple: "<em>Can I build this full-stack application that works?</em>"</p>
<p>If you could write code, connect to a few APIs, and build a working interface, companies were willing to hire you. They viewed junior developers as an investment. The expectation was that you should be trainable: you would come in, write standard boilerplate code, and learn the complexities of the system architecture on the job. The industry had the budget and patience for that learning curve.</p>
<p>But while memorizing the syntax and completing Udemy courses, the tooling was quietly evolving. Today, AI has taken that to a different extreme.</p>
<p>A significant portion of what we used to learn manually can now be generated, assisted, and suggested by AI in seconds.</p>
<ul>
<li><p>Need a basic Express server setup with rate limiting and CORS integrated? Can be generated.</p>
</li>
<li><p>Need a responsive navigation bar written in React? Can be assisted.</p>
</li>
<li><p>Need a standard SQL query to fetch company data? Can be suggested.</p>
</li>
</ul>
<p>If a machine can do something exponentially faster, cheaper, and reasonably well, that specific task stops being the differentiator in the job market. So, when people say AI is replacing junior developers, what they mean is that AI has automated the execution of these surface-level tasks.</p>
<p>But does it mean developers are no longer needed? No, it means the value of our work has moved up the stack. Building a TODO app, a Weather dashboard, or website clones is no longer a portfolio item. They're just your warm-up exercises.</p>
<h2 id="heading-lets-decode-the-ai-is-taking-jobs-myth">Let's Decode the "AI is Taking Jobs" Myth</h2>
<p>Traditionally, software engineers were given requirements: they wrote code, and they ensured it worked. The value of a software engineer was tied to their work execution. Even in interviews, the emphasis was on effort and memory:</p>
<ul>
<li><p>Can you write a linked list from scratch?</p>
</li>
<li><p>Can you check if this text is a palindrome?</p>
</li>
<li><p>Can you find the duplicates in this array of numbers?</p>
</li>
</ul>
<p>If you were a developer who put in long hours analyzing problem statements, manually debugging critical issues, and hand-crafting thousands of lines of source code, you were seen as a dedicated, high-valued employee.</p>
<p>Today, the effort alone is no longer a metric for success.</p>
<p>If you spend hours writing regular expressions or standard authentication flows that an AI agent can scaffold within two minutes, the industry doesn't reward you for your six hours of hard work. The industry asks: "<em>What value did you add beyond what the machine generated?</em>"</p>
<p>This is an uncomfortable truth, but accepting it could be the turning point in your career. Once you accept that AI can write code, your mindset shifts. You start accepting that you no longer have to worry about your execution speed, and you need to focus on <code>System Composition</code> and <code>Abstract Thinking</code>.</p>
<p>If you're a front-end developer today, your job is no longer limited to translating a Figma design into pixel-perfect React components. An AI coding assistant can do 80% of that in a few constructive prompts. Your job role expectations as a front-end developer are now shifted to:</p>
<ul>
<li><p>When that UI connects to the backend, and 10K users log in concurrently, how does the system behave?</p>
</li>
<li><p>Suppose a customer has an SLA (Service Level Agreement) stating that the dashboard must render with all data in 1.2 seconds on a slow 4G network, in 500 ms on a fast 4G network, and in 12 ms on a 5G network. How do you architect your Next.js application to meet that?</p>
</li>
<li><p>Are you leveraging server-side rendering, static generation, or edge caching correctly?</p>
</li>
<li><p>How does the application behave for users depending on screen readers?</p>
</li>
</ul>
<p>Source code is no longer the primary output. It should be the byproduct of your thinking and reasoning. You need to anticipate edge cases, and most importantly, you need to take ownership.</p>
<p>AI can write an API, but AI can't sit in a meeting with a furious client and explain why the production database went down. AI cann't own the consequences of a system failure. That accountability belongs entirely to you.</p>
<h2 id="heading-applying-a-clean-architecture">Applying a Clean Architecture</h2>
<p>Suppose you ask an LLM to build a complex application, say, an e-commerce product dashboard with sorting, filtering, and pagination. It will gladly generate the code that you'll be able to run and render on the browser. Bur AI has a very peculiar tendency in that it loves to build monoliths.</p>
<p>The AI will likely output a massive 1000+ line React component. The state management, UI rendering, data fetching, and business logic will be clubbed together in a single file. So it'll technically work in the browser, but it will be a nightmare to test, maintain, and scale.</p>
<p>This is where the human software engineers come in. A modern engineer understands <a href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">clean code principles and design patterns</a>. Instead of accepting the monolith AI output blindly, the engineer thinks in terms of LEGO-block compositions of React components.</p>
<p>A capable engineer looks into the requirements and thinks, " We shouldn't put everything in a single file. Let's use the <a href="https://youtu.be/LglWulOqh6k">Compound Components Pattern</a> here to make the UI flexible. Let's use the <a href="https://youtu.be/_LBgDy0j-Os">Slot Pattern</a> to create holes in our layout so consumers of this component can pass in their own custom elements without breaking the underlying logic."</p>
<p>You apply abstract thinking. You ask architectural questions:</p>
<ul>
<li><p>How are we managing side effects vs. the data fetching?</p>
</li>
<li><p>Can we swap out the payment provider later with a very small code change?</p>
</li>
<li><p>What happens if the network drops while the user is filtering?</p>
</li>
</ul>
<p>AI provides us with the bare metal raw materials. We need to provide the engineering discipline on top of it to make it production-ready.</p>
<h2 id="heading-a-practical-ai-era-engineering-roadmap">A Practical, AI-Era Engineering Roadmap</h2>
<p>Now, it's time to think about how to bridge the gap between a tutorial-driven developer and a modern, impact-driven engineer. Here is a practical stage-by-stage roadmap for you.</p>
<h3 id="heading-step-1-strengthen-your-fundamentals">Step 1: Strengthen Your Fundamentals</h3>
<p>You can't use AI effectively if you don't understand the code it generates. In the past, a surface-level knowledge of a framework would have been enough for you to execute your tasks. You might have gotten away without knowing the "under the hood" aspects of it.</p>
<p>Today, AI abstracts the frameworks. If something breaks underneath, you're multiple layers away from the actual problem. Having a strong fundamental knowledge will help you to battle this situation, and you'll enjoy working with AI even more.</p>
<p>You must go deep into the fundamentals of Computer Science &amp; Web Technologies:</p>
<ul>
<li><p>How does the internet work? <a href="https://www.freecodecamp.org/news/computer-networking-fundamentals/">Understand Networking basics</a>.</p>
</li>
<li><p>Don't just learn to write JavaScript promises. Learn about the event loop. Understand the call stack, the microtask queue, and how memory allocation works.</p>
</li>
<li><p>When a React application has a memory leak, AI will struggle to find it if it spans multiple files. You need to know how to use Chrome DevTools memory profilers.</p>
</li>
<li><p>Instead of focusing on random algorithmic puzzles, focus on applied abstract thinking. If you're building a real-time collaborative document editor, how do you manage the data structure for concurrent edits? This is how DSA is tested in this era of technical interviews.</p>
</li>
</ul>
<h3 id="heading-step-2-build-real-uncomfortable-systems">Step 2: Build Real (Uncomfortable) Systems</h3>
<p>Stop building TODO apps. Stop building basic CRUD applications that only work in an ideal, localhost environment. Learn to build systems to handle failures.</p>
<p>Instead of building a generic e-commerce clone, build an Automated E-book Delivery and Waitlist system. For example,</p>
<ul>
<li><p><strong>The stack</strong>: Tanstack Start for the front end, NestJS for the API, Supabase for the database, Razorpay for payment processing, Firebase for social logins, and Resend for email delivery.</p>
</li>
<li><p><strong>The challenge</strong>: Don't be satisfied with just making the happy path work. What happens if the Razorpay webhook fails to reach your server after a user pays? How do you implement a retry mechanism? How do you secure your Supabase database with RLS (Row Level Security) so users can only download the book they paid for? How do you prevent duplicate sign-ups on your waitlist?</p>
</li>
</ul>
<p>When you build systems like this, you naturally run into complex real-world problems. Solving these, you'll build the exact engineering muscles that companies are now desperate to hire.</p>
<h3 id="heading-step-3-master-the-art-of-debugging">Step 3: Master the Art of Debugging</h3>
<p>When the system breaks in production, panic starts. The developers who can stay calm, isolate assumptions, trace problems, and fix them are invaluable.</p>
<p>AI is great at explaining isolated error messages, but it can't easily debug a distributed system where a frontend state mismatch is caused by a race condition in a backend microservice. That's on you to burn the midnight oil and get it done.</p>
<p>As a software developer at any level:</p>
<ul>
<li><p>Learn how to implement structured logging in your code.</p>
</li>
<li><p>Learn how to read a stack trace systematically.</p>
</li>
<li><p>Practice fixing performance bottlenecks without causing regressions in other parts of the application.</p>
</li>
<li><p>Understand <a href="https://www.freecodecamp.org/news/how-to-track-and-analyze-web-vitals-to-improve-seo/">Web Vitals</a> (LCP, CLS, INP, and so on.) and how to profile a slow rendering page.</p>
</li>
</ul>
<h3 id="heading-step-4-use-ai-as-a-tool-not-as-a-crutch">Step 4: Use AI as a Tool, Not as a Crutch</h3>
<p>First of all, stop blind copy-pasting AI responses. Treat AI like an incredibly fast, highly confident, but slightly carefree junior developer.</p>
<ul>
<li><p><strong>Use it for boilerplate</strong>: Need an ExpressJS setup? Zustand store set up? Generate it.</p>
</li>
<li><p><strong>Use it for research</strong>: Learning a new thing like Rust, Go, or Cybersecurity? Prompt the AI to generate a 30-day learning roadmap tailored to your existing programming language knowledge.</p>
</li>
<li><p><strong>Use it for content</strong>: Want to write a READ ME file? Want to brainstorm a DRAFT idea? AI can be your companion.</p>
</li>
<li><p><strong>Use it for scaffolding</strong>: Need to write unit tests for a utility function? Let AI scaffold the test suites.</p>
</li>
</ul>
<p>Note, every time you copy code from an LLM without understanding it, you're creating tech debt unknowingly. Your job is to make the AI's response as optimal as possible for production.</p>
<p>If you prompt an AI to write a complex data aggregation logic, and it outputs 72 lines of reducer function, don't just copy-paste it. Read it line-by-line, and ask yourself: Is this optimal? What's the Big O time complexity of this code? Can I make it more readable?</p>
<h3 id="heading-step-5-establishing-a-strong-proof-of-work">Step 5: Establishing a Strong Proof of Work</h3>
<p>A résumé listing your skills or a certificate from a bootcamp aren't very strong proof of work achievements today.</p>
<p>Strong proof of work looks like:</p>
<ul>
<li><p>A GitHub repository featuring a complex real-world application with a beautifully written README explaining the architectural choices.</p>
</li>
<li><p>Meaningful contributions to the open-source projects where your code had to pass serious reviews from senior maintainers.</p>
</li>
<li><p>Writing deep tech articles or LinkedIn posts explaining how you solved a difficult rendering bug or why you chose a specific database schema for a project.</p>
</li>
<li><p>Participating in a hackathon to build something that is either trendy, or has potential to go viral, or can bring revenue, or a combination of all of these.</p>
</li>
</ul>
<p>Don't just code in silos. Build in public. Explain your thought process socially. When you articulate your engineering thoughts and decisions publicly, it separates you from millions of developers who are just relying on the response from ChatGPT or any other AI tools.</p>
<p>The diagram below captures all five steps visually for you to connect them and revisit at any point in time.</p>
<p><a href="https://www.tapascript.io/techframes/software-developer-roadmap-in-ai-age"><img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/f10119e2-91b5-462c-bcc3-ba0f924a6d2a.png" alt="A Practical Roadmap to Consider" style="display:block;margin:0 auto" width="600" height="400" loading="lazy"></a></p>
<p><em>You can download this tech frame and many others</em> <a href="https://www.tapascript.io/techframes"><em>from here</em></a><em>.</em></p>
<h2 id="heading-the-must-needed-mindset-shift">The Must-Needed Mindset Shift</h2>
<blockquote>
<p>"It all begins and ends in your mind. What you give power to, has power over you" - by Leon Brown</p>
</blockquote>
<p>If you're currently looking for a job, you need to immediately stop asking people, "Will I get a Job?" It's the wrong question. You can't be sure you'll get a job if you don't have a convincing reason why a company should hire you.</p>
<p>Instead, look at the job descriptions. Look at the companies you admire. Then ask yourself: "<em>Why should they hire me in today's circumstances?</em>"</p>
<p>If you don't have a convincing answer yet, that's perfectly fine! That's your baseline, and you've identified your skill gap. Your mission now is to bridge that gap.</p>
<p>We've entered a phase where the definition of a software engineer is sharper and more demanding than ever before. The bar is higher, but the expectations are clearer. If you refuse to adapt and insist on staying at the level of simple execution, the path forward will likely be incredibly difficult. You'll compete with AI tools that never sleep and developers who are utilizing those tools to do the work of three people.</p>
<p>But if you embrace the shift and move toward abstract thinking, deep fundamentals, system architecture, and true accountability, the opportunities are limitless. You're no longer competing with everyone. Your competition will be with a small set of developers willing to take up the challenge of evolving.</p>
<p>The software engineering of the future (read: "today") is not about typing code syntax into an editor. It's about understanding what to build, why to build it, how it impacts the business, how to design it to last, and how to use AI as a tool to accelerate things exponentially.</p>
<h2 id="heading-if-youve-read-this-far">If You've Read This Far...</h2>
<p>Thank You!</p>
<p>I'm a Full Stack Software Engineer with more than two decades of experience in building products and people. At present, I'm pushing my startup, <a href="https://www.creowis.com/">CreoWis Technologies</a>, and teaching/mentoring developers on my <a href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube channel, tapaScript</a>.</p>
<p>I'm thrilled to publish my 50th article on the freeCodeCamp platform, and it makes me exceptionally proud to give back my knowledge to the developer community. If you want to connect with me,</p>
<ul>
<li><p>Follow on <a href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> and <a href="https://x.com/tapasadhikary">X</a></p>
</li>
<li><p>Subscribe to my <a href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a></p>
</li>
<li><p>Catch up with my <a href="https://www.tapascript.io/books/react-clean-code-rule-book">React Clean Code Rules Book</a></p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Override API Responses and Headers in Chrome DevTools: A Step-by-Step Guide ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever faced a situation as a frontend developer where you needed to show a demo to your product manager, and something was broken in the API response? Or, a production bug where you were block ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-override-api-responses-and-headers-in-chrome-devtools/</link>
                <guid isPermaLink="false">69c5a33110e664c5da34c6d3</guid>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ APIs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Thu, 26 Mar 2026 21:20:49 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/a2fee8e9-cb71-4065-af8e-ef0357e6ca2c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever faced a situation as a frontend developer where you needed to show a demo to your product manager, and something was broken in the API response? Or, a production bug where you were blocked by waiting on your backend team to provide you with a fix to implement further on the frontend?</p>
<p>To make things even worse, how about a CORS error that completely prevented you from showing the page?</p>
<p>It happens, right? Going back to the backend team and getting a quick fix for these issues would be ideal, but may not be realistic in most cases. It depends on the availability of the backend developers, the priority items they're working on, communication protocols between teams, and even interpersonal relationships.</p>
<p>Now, the question is, can you afford to wait? Wait for things to work in your favour within the given deadline so that you can show that demo or deliver the work to your customer? The answer is NO. You may not have that luxury.</p>
<p>Today, in this article, you'll learn a couple of mind-blowing tips and tricks that will save you from these situations. You'll understand how to set up your Chrome browser so that you can continue with your frontend development even when the backend API returns an incorrect response or a CORS error.</p>
<p>This is a step-by-step guide that'll help make you comfortable with all the required configurations and get you set up to use it on your web projects. This guide is also available as a video tutorial as part of the <a href="https://www.youtube.com/playlist?list=PLIJrr73KDmRwT8Msc4H3_CP5Tf8MqqqVZ">Thinking in Debugging</a> series. You can check it out if you’d like:</p>
<div class="embed-wrapper"><iframe width="560" height="315" src="https://www.youtube.com/embed/ndrPcDNmwFk" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>

<p>Let's get started with the problems and their solutions.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a href="#heading-problem-1-backend-response-is-wrong">Problem 1: The Backend Response Is Wrong</a></p>
</li>
<li><p><a href="#heading-problem-2-validating-a-ui-scenario-without-backend-changes">Problem 2: Validating a UI Scenario Without Backend Changes</a></p>
</li>
<li><p><a href="#heading-problem-3-handling-cors-errors">Problem 3: Handling CORS Errors</a></p>
</li>
<li><p><a href="#heading-additional-tips">Additional Tips</a></p>
<ul>
<li><p><a href="#heading-applying-overrides-globally">Applying Overrides Globally</a></p>
</li>
<li><p><a href="#heading-disabling-or-removing-overrides">Disabling or Removing Overrides</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-learn-more-from-the-thinking-in-debugging-mindset">Learn More From the Thinking in Debugging Mindset</a></p>
</li>
<li><p><a href="#heading-before-we-end">Before We End…</a></p>
</li>
</ol>
<h2 id="heading-problem-1-the-backend-response-is-wrong">Problem 1: The Backend Response Is Wrong</h2>
<p>Here is a classic case of a wrong API response, but you still need to continue with your frontend work.</p>
<p>Take a look at the image below. Do you see that something is off? Yeah, on the first card, the spelling of <code>Banana</code> seems to be misspelled as <code>Banananana</code>. This user interface is constructed using the data we have received as an API response.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/2bef7ac2-98c0-419a-b783-ee64900f8121.png" alt="Incorrect spelling of banana on first card" style="display:block;margin:0 auto" width="2076" height="1546" loading="lazy">

<p>We can go to the backend team and request that they fix it as soon as possible. But it may not happen until the next sprint starts, which might be 15 days from now.</p>
<p>So, what can we do to continue with our work and all the validations on the frontend side? We can use the <code>Content Overriding</code> feature of the Chrome browser to mitigate this situation.</p>
<h3 id="heading-how-to-use-content-overriding">How to Use <code>Content Overriding</code></h3>
<p>First, open up the DevTools of your Chrome browser by pressing the F12 (on Mac, Cmd+F12) key. Then move to the network tab and inspect the API request that returns the incorrect response.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/f9689133-c7cd-400e-b0cc-5275fe1ca7ec.png" alt="Network Request" style="display:block;margin:0 auto" width="1870" height="808" loading="lazy">

<p>Next, right-click on the API request and select the <code>Override content</code> option from the context menu.</p>
<p>You may wonder what content means here, and what I am overriding? You're overriding the API response so that it can reflect on the UI locally.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/31d4e340-d9fa-4dec-81cc-08fbf644aa58.png" alt="Override Content Option" style="display:block;margin:0 auto" width="814" height="1090" loading="lazy">

<p>This will bring up a UI at the top where you can select a folder to store override files. It's important to understand that all the content overrides are locally stored on your machine's hard disk. This means you can use these persisted overrides again and again until someone fixes the issue permanently at the backend.</p>
<p>Now click on the <code>Select folder</code> button.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/7d238b9d-146c-4592-9008-26c7c189a0de.png" alt="Select a Folder" style="display:block;margin:0 auto" width="1890" height="1530" loading="lazy">

<p>This will open up the folder explorer for you. Create a new folder and select it, or select an existing folder where you want to save the overrides. In my case, I've named the folder as <code>debug_devtools</code>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/7bc13c7b-0ffa-442a-899e-98a805fcddac.png" alt="Select a Folder" style="display:block;margin:0 auto" width="1564" height="1062" loading="lazy">

<p>Now, Chrome DevTools will ask for confirmation that you're allowing DevTools to edit files on your local system. Just click on the <code>Allow</code> button.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/07ff30f6-8bef-40c3-aee9-bcd55545c67f.png" alt="Allow" style="display:block;margin:0 auto" width="1504" height="682" loading="lazy">

<p>That's all for the setup. Now, you'll find the same response in the editable mode under the <code>Sources</code> tab of DevTools. Let's take a deeper look at the image below:</p>
<ol>
<li><p>The Local overrides are listed under the <code>Sources &gt; Oveerides</code> tab of the DevTools.</p>
</li>
<li><p>On the left side, the <code>Enable Local Overrides</code> checkbox is selected, and the overrides are listed below. You can find the same folder you created before, and under that, you'll see another folder called <code>localhost:3001</code> and a file called <code>edibles</code> under it. The localhost:3001 folder name is related to the API endpoint namespace we're connecting to. The edibles file name under it goes with the request name.</p>
</li>
<li><p>On the right side, you can see the content (that is, the response to the edibles request) in editable mode.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/fc918250-c1ab-4b56-8505-3032e698b8cc.png" alt="fc918250-c1ab-4b56-8505-3032e698b8cc" style="display:block;margin:0 auto" width="1818" height="1410" loading="lazy">

<p>You can even cross-check now by traversing to the file system's <code>debug_devtools</code> folder. You should find the same folders and files as you saw in the DevTools.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/81fd4e82-ae7d-4d07-88d8-5a757edbc3ef.png" alt="Response in folder" style="display:block;margin:0 auto" width="1460" height="662" loading="lazy">

<p>You can open up the <code>edibles</code> file. The file content should match exactly the response you saw before.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/4ba75464-0a29-4f11-9bc6-be0463e10dd5.png" alt="edibles content" style="display:block;margin:0 auto" width="1686" height="1148" loading="lazy">

<p>Now, it's time to override. Coming to the Sources tab's editable response panel, you can fix the spelling. Save your changes using Ctrl + S (or Cmd + S).</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/c33701f0-ddb1-478c-8fe6-d68ddf8dd638.png" alt="edit text" style="display:block;margin:0 auto" width="1634" height="700" loading="lazy">

<p>Now, hard refresh your browser. You should be able to see your change reflected on the UI.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/1414be9d-adf4-41a6-8cbc-d115a49bb8a6.png" alt="Banana Fixed" style="display:block;margin:0 auto" width="2982" height="1590" loading="lazy">

<p>Awesome!! You can now share this overridden response (the <code>edibles</code> file) with other developers to point to from their Chrome DevTools to get the same local fix until the backend fixes it.</p>
<h2 id="heading-problem-2-validating-a-ui-scenario-without-backend-changes">Problem 2: Validating a UI Scenario Without Backend Changes</h2>
<p>Imagine you need to validate that certain items are low in stock on an item listing page. If the stock quantity of an item hits 50 or below, you want to show a <code>Low Stock</code> label for that item.</p>
<p>Now, what if the API response doesn't return a quantity of 50 or below? Content overriding can come to the rescue once again!</p>
<p>You can edit the response to set the quantity value to 50 or below and follow the same process as before to reflect the change on the UI. Look at the image below:</p>
<ol>
<li><p>We have edited the quantity on the right-side panel.</p>
</li>
<li><p>Once saved and refreshed, we not only see the updated count on the UI, but it also runs the underlying JavaScript logic to show the <code>Low Stock</code> label automatically. This is a superpower.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/77b8578e-ecc9-4397-b980-e24cc0ab099e.png" alt="Stock" style="display:block;margin:0 auto" width="2660" height="684" loading="lazy">

<h2 id="heading-problem-3-handling-cors-errors">Problem 3: Handling CORS Errors</h2>
<p><a href="https://www.youtube.com/shorts/lPiQClBVYY4">Cross-Origin Resource Sharing (CORS)</a> is a browser security feature that allows a web server to explicitly grant requests coming from a domain other than its own. By default, browsers don't allow these cross-origin requests and follow a strict rule called <code>Same Origin Resource Sharing</code>.</p>
<p>In many cases, your API server and the web server could be hosted on different domains. In those cases, when the web application attempts to access an API, it faces the CORS error.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/f739eb08-6bb1-4534-9080-0417d511396c.png" alt="CORS Error" style="display:block;margin:0 auto" width="2982" height="742" loading="lazy">

<p>On the server side, you need to have explicit configurations to allow cross-origin requests. For example, you need to add the following response headers:</p>
<pre><code class="language-shell">Access-Control-Allow-Origin: http://localhost:5174
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: *
</code></pre>
<p>So, again, it may not be guaranteed that your CORS error will be resolved at the server side as soon as you want. But you cann't afford to get blocked due to it. So, what's the way around? Yes! The overriding, but this time, overriding the response header.</p>
<p>Go to the network tab of the Chrome DevTools and right-click on the request that has the CORS error. Now, select the <code>Override headers</code> option from the context menu.</p>
<p>By the way, have you noticed that the <code>Override content</code> option is disabled here? This is because we don't have any response as content from this request, as it got an error.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/4d81fbb1-e960-48f2-bdd7-597e686faff6.png" alt="4d81fbb1-e960-48f2-bdd7-597e686faff6" style="display:block;margin:0 auto" width="1280" height="966" loading="lazy">

<p>Clicking on the <code>Overriding headers</code> will take you to the <code>Headers</code> tab where you can find the option to add additional headers to the response headers. Click on the <code>+ Add header</code> button to add the CORS-related headers.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/9acdbde3-0b12-4cef-9437-844ca92d502c.png" alt="Add Header" style="display:block;margin:0 auto" width="1736" height="1036" loading="lazy">

<p>Add all three headers with their respective values one by one:</p>
<pre><code class="language-bash">Access-Control-Allow-Origin: http://localhost:5174 
Access-Control-Allow-Methods: GET 
Access-Control-Allow-Headers: *
</code></pre>
<p>Each of these headers has its own important use:</p>
<ol>
<li><p>With the <code>Access-Control-Allow-Origin</code> header, you can specify the origin domains that are allowed to have a cross-origin request to the server. In this case, the value is <code>http://localhost:5174</code> where we're running a Vite-based ReactJS app.</p>
</li>
<li><p>The header <code>Access-Control-Allow-Methods</code> specifies what kind of HTTP methods are allowed from the originating domain. In this case, we're allowing only the <code>GET</code> method.</p>
</li>
<li><p>The <code>Access-Control-Allow-Headers</code> HTTP response headers specify which HTTP headers can be safely used during a cross-origin request.</p>
</li>
</ol>
<p>Alright, let's add them all and save.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/02fc7203-9ca6-47cf-a478-f20d928ece54.png" alt="CORS Headers" style="display:block;margin:0 auto" width="1714" height="690" loading="lazy">

<p>Like overriding content, overriding the header will also create a folder with the context of the server domain, and under that, a file called <code>.headers</code>. As the file name starts with a dot(.), it may be treated as a hidden file by most operating systems. So make sure you go through the OS settings to view the hidden files to view this file.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/ab93a8d4-b87d-4cf4-8a0e-1d6ce4d26537.png" alt="Hidden headers file" style="display:block;margin:0 auto" width="1394" height="530" loading="lazy">

<p>Once you view and open the file, you'll see the headers you have added with overriding.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/8dfe3ee3-2250-489a-a465-f9796934a470.png" alt="headers content" style="display:block;margin:0 auto" width="1678" height="1122" loading="lazy">

<p>Now, hard refresh your browser, and try to perform the same operation that was giving you the CORS error before. Wow, the error has gone now! You should be able to see the request success and the response coming back from the server.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/351dcb19-af06-4058-b08d-d449b92ab898.png" alt="User Data" style="display:block;margin:0 auto" width="2558" height="1080" loading="lazy">

<p>Just imagine, not a single line of server-side code changes, and you're unblocked so you can move forward with your client-side UI work. Fantastic, isn't it?</p>
<h2 id="heading-additional-tips">Additional Tips</h2>
<p>Before we end, let's learn about a couple more handy tips.</p>
<h3 id="heading-applying-overrides-globally">Applying Overrides Globally</h3>
<p>We applied the CORS error-related header overriding only on the <code>/user</code> API endpoint. What if you need to apply the same overriding for other endpoints, too? You can do it easily by following these simple steps:</p>
<ol>
<li><p>Navigate to the <code>Sources</code> tab.</p>
</li>
<li><p>Select the <code>Overrides</code> sub-tab.</p>
</li>
<li><p>Click on the <code>.headers</code> override.</p>
</li>
<li><p>On the right-side panel, change the value of the <code>Apply to</code> to <code>*</code>.</p>
</li>
</ol>
<p>That's it. Now, the same response headers will be applied as overrides for all the endpoints.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/c15a94e4-a2e9-48b1-8ae1-c781424be388.png" alt="Apply To" style="display:block;margin:0 auto" width="1678" height="666" loading="lazy">

<h3 id="heading-disabling-or-removing-overrides">Disabling or Removing Overrides</h3>
<p>Sometimes, you might want to disable or remove overrides. To disable overrides without removing them, just uncheck the <code>Enable Local Overrides</code> checkbox. To remove all the overrides permanently, click on the stop icon at the top-right corner. Also, to selectively remove an override, right-click on it and delete.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/80c59dc2-0eea-48ad-b499-be1d4493512c.png" alt="80c59dc2-0eea-48ad-b499-be1d4493512c" style="display:block;margin:0 auto" width="848" height="642" loading="lazy">

<h2 id="heading-learn-more-from-the-thinking-in-debugging-mindset">Learn More From the Thinking in Debugging Mindset</h2>
<p>If you've liked this practical, example-driven guide, you'll enjoy my other debugging-related content from the <em>Thinking in Debugging</em> series. Please <a href="https://www.youtube.com/playlist?list=PLIJrr73KDmRwT8Msc4H3_CP5Tf8MqqqVZ">check it out</a>.</p>
<p><a href="https://www.youtube.com/playlist?list=PLIJrr73KDmRwT8Msc4H3_CP5Tf8MqqqVZ"><img src="https://cdn.hashnode.com/uploads/covers/5c9bb4026656f09759cdc1f0/9046f04f-71f1-4303-b39c-7267fd3814bc.png" alt="Thinking in Debugging" style="display:block;margin:0 auto" width="2330" height="1046" loading="lazy"></a></p>
<h2 id="heading-before-we-end">Before We End…</h2>
<p>That’s all! I hope you found this insightful.</p>
<p>Let’s connect:</p>
<ul>
<li><p>Subscribe to my <a href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</p>
</li>
<li><p>Check out my courses, <a href="https://www.youtube.com/playlist?list=PLIJrr73KDmRw2Fwwjt6cPC_tk5vcSICCu">40 Days of JavaScript</a> and <a href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">15 Days of React Design Patterns</a></p>
</li>
<li><p>Follow on <a href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Join my <a href="https://discord.gg/zHHXx4vc2H">Discord Server</a>, and let’s learn together.</p>
</li>
<li><p>Follow my work on <a href="https://github.com/tapascript">GitHub</a>.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Modern React Data Fetching Handbook: Suspense, use(), and ErrorBoundary Explained ]]>
                </title>
                <description>
                    <![CDATA[ Most React developers don’t break the data fetching process all at once. It usually degrades gradually, slowly. Traditionally, you may have used a useEffect here, a loading flag there, and an error state along with it to tackle data fetching. Moving ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-modern-react-data-fetching-handbook-suspense-use-and-errorboundary-explained/</link>
                <guid isPermaLink="false">698def824dcd2f8caf2d36ef</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Thu, 12 Feb 2026 15:19:30 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1770847474747/df826db8-4d18-45f5-a4aa-bfafa9c3aa80.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Most React developers don’t break the data fetching process all at once. It usually degrades gradually, slowly.</p>
<p>Traditionally, you may have used a <code>useEffect</code> here, a loading flag there, and an error state along with it to tackle data fetching. Moving forward, another fetch depended on the first one, then a second useEffect, and another loading and error state.</p>
<p>This likely continued until you started feeling like you were writing code that you yourself could’t even maintain in the future.</p>
<p>Requests that should run in parallel started running sequentially. Components re-rendered unnecessarily just to satisfy another data fetch request-response. Loading spinners appeared when nothing meaningfully changed. Error states got scattered inside the component.</p>
<p>Well, none of these things are React’s problem. These are core design problems you should be aware of while coding your React Apps.</p>
<p>In this handbook, we’ll walk through one React Pattern that fixes data fetching at the architecture level without ignoring real data dependencies, and without introducing any new magic. If data fetching in React has ever felt harder than it should be, this pattern will make even more sense to you.</p>
<p>You’ll learn how to use React’s <code>Suspense</code> with the recently introduced <code>use()</code> API to handle data fetching smoothly. In case of errors, you’ll learn how an <code>Error Boundary</code> can help handle them gracefully.</p>
<p>Give this one a read, and code along to get a better grip on this pattern’s mental model.</p>
<p>This handbook is also available as a video tutorial as part of the <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">15 Days of React Design Patterns</a> <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">initiative</a>. You can check it out if you’d like:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/tY8rhkLdr2A" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>We’ll use a lot of source code to demonstrate the problems with the traditional data-fetching approach and how the Suspense Pattern can improve things. I would suggest that you try the code as you read. But if you want to take a look at the source code ahead of time, you can find it on the <a target="_blank" href="https://github.com/tapascript/15-days-of-react-design-patterns/tree/main/day-16">tapaScript GitHub</a>.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-the-traditional-way-of-data-fetching-in-react">The Traditional Way of Data Fetching in React</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-the-problem-with-the-traditional-way">The Problem with the Traditional Way</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-lets-build-a-dashboard-with-the-traditional-data-fetching-approach">Let’s Build a Dashboard with the Traditional Data Fetching Approach</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-suspense">What is Suspense?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-use-api-in-react">What is the <code>use()</code> API in React?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-suspense-and-the-use-api-for-data-fetching">How to Use Suspense and the <code>use()</code> API for Data Fetching</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-lets-build-the-dashboard-with-suspense-and-the-use-api">Let’s Build the Dashboard with Suspense and the <code>use()</code> API</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-project-setup">Project Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-api-services">API Services</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-a-centralised-user-resource">Create a Centralised User Resource</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-individual-components">Create Individual Components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-the-fallback-ui">Create the Fallback UI</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-the-dashboard-component-with-suspense">Create the Dashboard Component with Suspense</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-run-the-dashboard-app">Run the Dashboard App</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-handle-error-scenarios-with-error-boundaries">How to Handle Error Scenarios with Error Boundaries?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-error-boundary">Error Boundary</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-suspense-and-error-boundary">Suspense and Error Boundary</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-learn-from-the-15-days-of-react-design-patterns">Learn from the 15 Days of React Design Patterns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-before-we-end">Before We End…</a></p>
</li>
</ol>
<h2 id="heading-the-traditional-way-of-data-fetching-in-react">The Traditional Way of Data Fetching in React</h2>
<p>To understand why data fetching can become painful in React, we first need to understand how React works under the hood.</p>
<p>React works in phases. It doesn’t do everything at once. At a high level, every update in React goes through three distinct phases:</p>
<ul>
<li><p><strong>Render phase</strong> – React figures out <em>what</em> the UI should look like</p>
</li>
<li><p><strong>Commit phase</strong> – React applies those changes to the DOM</p>
</li>
<li><p><strong>Effect phase</strong> – React synchronises with the outside world</p>
</li>
</ul>
<p>This separation is intentional. It’s what allows React to be predictable, interruptible, and efficient.</p>
<p>Now, let’s see where data fetching with <code>useEffect</code> fits into this picture:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770089281941/9a0dbc5d-6b45-4813-9e62-8bc4cbad82ea.png" alt="The useEffect Phases" class="image--center mx-auto" width="1642" height="781" loading="lazy"></p>
<p>Where does <code>useEffect</code> actually run? It doesn’t run during rendering. It runs after React has already committed the UI to the DOM.</p>
<p>That means the flow looks like this:</p>
<ol>
<li><p>React renders the component (without data)</p>
</li>
<li><p>React commits the UI</p>
</li>
<li><p>useEffect runs</p>
</li>
<li><p>Data fetching starts</p>
</li>
<li><p>State updates when the data arrives</p>
</li>
<li><p>React renders again</p>
</li>
</ol>
<pre><code class="lang-javascript">useEffect(<span class="hljs-function">() =&gt;</span> {
  fetchData().then(setData);
}, []);
</code></pre>
<p>Hence, the fetch only starts after the UI has already rendered.</p>
<h3 id="heading-the-problem-with-the-traditional-way">The Problem with the Traditional Way</h3>
<p>Consider a very common scenario: you fetch a user, and then fetch related data using the user ID.</p>
<p>The traditional React data fetching solution would look like this:</p>
<pre><code class="lang-javascript">useEffect(<span class="hljs-function">() =&gt;</span> {
  fetchUser().then(setUser);
}, []);

useEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">if</span> (!user) <span class="hljs-keyword">return</span>;
  fetchOrders(user.id).then(setOrders);
}, [user]);
</code></pre>
<p>What actually happens is:</p>
<ul>
<li><p>The component renders</p>
</li>
<li><p>React commits the UI</p>
</li>
<li><p>The first effect runs and fetches the user</p>
</li>
<li><p>React re-renders</p>
</li>
<li><p>The second effect runs and fetches orders</p>
</li>
</ul>
<p>Even if the network is fast, the requests are forced to start one after another, because each fetch is triggered by a render that only happens after the previous fetch completes.</p>
<p>This paradigm of data fetching is called <code>Fetch-On-Render</code>. The fetching logic is no longer controlled by data dependencies – it’s controlled by render timing. But that’s not all. There are other problems with this approach: you create and maintain unnecessary states.</p>
<p>Now, let’s see both these problems in action by building something practical.</p>
<h2 id="heading-lets-build-a-dashboard-with-the-traditional-data-fetching-approach">Let’s Build a Dashboard with the Traditional Data Fetching Approach</h2>
<p>Let’s build a simple dashboard with the traditional data fetching approach using the <code>useEffect</code> hook at the center. The dashboard will have four primary sections:</p>
<ul>
<li><p>A Static heading.</p>
</li>
<li><p>A <code>Profile</code> section welcoming the user with their name.</p>
</li>
<li><p>An <code>Order</code> section listing the items ordered by the user.</p>
</li>
<li><p>An <code>Analytics</code> section showing a few metrics for the same user.</p>
</li>
</ul>
<p>You can visualise it like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770184122812/d8cd8d82-9f38-4ab6-b029-e2e68dbbd66a.png" alt="Dashboard" class="image--center mx-auto" width="806" height="919" loading="lazy"></p>
<p>The profile, order, and analytics sections should show the dynamic data of a user and their order and analytics. Hence, we’ll simulate three API calls to get the user details, order details, and the analytics data.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// API to fetch User</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUser</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      resolve({ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"Tapas"</span> });
    }, <span class="hljs-number">1500</span>);
  });
}

<span class="hljs-comment">// API to fetch the Orders of a User</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchOrders</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      resolve([
          <span class="hljs-string">`Order A for user <span class="hljs-subst">${userId}</span>`</span>,
          <span class="hljs-string">`Order B for user <span class="hljs-subst">${userId}</span>`</span>
      ]);
    }, <span class="hljs-number">1500</span>);
  });
}

<span class="hljs-comment">// API to fetch the Analytics of a User</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchAnalytics</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      resolve({
        <span class="hljs-attr">revenue</span>: <span class="hljs-string">"$12,000"</span>,
        <span class="hljs-attr">growth</span>: <span class="hljs-string">"18%"</span>,
        userId
      });
    }, <span class="hljs-number">1500</span>);
  });
}
</code></pre>
<p>As you can see in this code:</p>
<ul>
<li><p>Each of the API functions returns a promise.</p>
</li>
<li><p>There is an intentional delay of 1.5 seconds using setTimeout to simulate the feel of a network call. The promise resolves after the delay passes.</p>
</li>
<li><p>Once the promise gets resolved, we get the data.</p>
</li>
</ul>
<p>Now, let’s create the Dashboard component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { fetchAnalytics, fetchOrders, fetchUser } <span class="hljs-keyword">from</span> <span class="hljs-string">"../api"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Dashboard</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [user, setUser] = useState(<span class="hljs-literal">null</span>);
    <span class="hljs-keyword">const</span> [orders, setOrders] = useState(<span class="hljs-literal">null</span>);
    <span class="hljs-keyword">const</span> [analytics, setAnalytics] = useState(<span class="hljs-literal">null</span>);

    <span class="hljs-comment">// Step 1: Fetch user</span>
    useEffect(<span class="hljs-function">() =&gt;</span> {
        fetchUser().then(setUser);
    }, []);

    <span class="hljs-comment">// Step 2: Fetch orders (depends on user)</span>
    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (!user) <span class="hljs-keyword">return</span>;
        fetchOrders(user.id).then(setOrders);
    }, [user]);

    <span class="hljs-comment">// Step 3: Fetch analytics (depends on user)</span>
    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (!user) <span class="hljs-keyword">return</span>;
        fetchAnalytics(user.id).then(setAnalytics);
    }, [user]);

    <span class="hljs-comment">// Logic to ensure that user, orders, and analytics data </span>
    <span class="hljs-comment">// loaded before we render them on JSX</span>
    <span class="hljs-keyword">if</span> (!user || !orders || !analytics) {
        <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl m-3"</span>&gt;</span>Loading dashboard...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
    }

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"m-2"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-5xl mb-12"</span>&gt;</span>📊 Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>Welcome, {user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl mt-3"</span>&gt;</span>Orders<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
                {orders.map((o) =&gt; (
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{o}</span>&gt;</span>
                        {o}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                ))}
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl mt-3"</span>&gt;</span>Analytics<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl"</span>&gt;</span>Revenue: {analytics.revenue}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl"</span>&gt;</span>Growth: {analytics.growth}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}
</code></pre>
<p>Let’s break it down:</p>
<ul>
<li><p>The first thing you’ll notice is that we have three states for holding the data of users, orders, and analytics.</p>
</li>
<li><p>Then we have three <code>useEffect</code>s to manage the fetching of data and updating the states.</p>
</li>
<li><p>Then we show the data values in the JSX.</p>
</li>
<li><p>We’re using a <code>Fetch-On-Render</code> methodology.</p>
</li>
</ul>
<p>However, in between, there’s an explicit logic to check if the user data, order data, or analytics data has been loaded. If the data are not loaded, then we don’t even process the JSX – rather, we show a loading message.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Logic to ensure that user, orders, and analytics data </span>
<span class="hljs-comment">// loaded before we render them on JSX</span>
<span class="hljs-keyword">if</span> (!user || !orders || !analytics) {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl m-3"</span>&gt;</span>Loading dashboard...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
}
</code></pre>
<p>This is good as a measure so that the UI doesn’t crash at runtime. But this is not a declarative approach. Since React is declarative, it would make more sense if we could handle this scenario in a declarative way as well.</p>
<p>In <code>Declarative programming</code>, you as a programmer don’t specify how to to solve certain problems. You declare what you want to achieve, and the programming language/framework takes care of the “how” part for you. When you specify the “how” part, it becomes <code>imperative</code>, not declarative.</p>
<p>React is declarative because you don’t specify how to update the browser DOM to render the UI changes. You declare them using JSX, and React takes care of it under the hood.</p>
<p>As an alternative to the explicit imperative logic like the above, you could also handle it using loading states. You could have loading states for profile, orders, and analytics. The loading states could decide when to show the data conditionally. But this approach needs additional state management and conditional rendering of JSX.</p>
<p>Along with these issues, think of handling errors! Again, you would need states for error handling and the conditional logic to show and hide the error messages. That’s too much to manage.</p>
<p>So, with the <code>useEffect</code> strategy, data fetching in React is not that effective. We need a better pattern to handle data along with loading states and errors.</p>
<p>But before we move on, I want to clarify that <code>useEffect</code> isn’t bad. It has a purpose, but sometimes we don’t use it as intended. If you’re someone who wants to learn the effective usages of this hook and how to debug it properly, you can <a target="_blank" href="https://www.youtube.com/watch?v=z2VnpJ6st-4">check out this session</a>.</p>
<h2 id="heading-what-is-suspense">What is Suspense?</h2>
<p>At its core, React <code>Suspense</code> is not a loading feature. It’s a rendering coordination mechanism. Suspense allows a component to tell React, “I’m not ready to be rendered, yet”. When that happens, React pauses rendering for that part of the tree and shows a fallback UI until the required data becomes available.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770193224537/fb10d206-11f0-4cdf-b984-bfcf07b19ae8.png" alt="Suspense Mechanism" class="image--center mx-auto" width="1296" height="1043" loading="lazy"></p>
<p>This is fundamentally different from how data fetching works with useEffect.</p>
<p>With the traditional <code>Fetch-On-Render</code> approach, React must first render a component before it’s allowed to start fetching data. Effects run after the commit phase, which means data fetching is always a reaction to rendering, never a prerequisite for it. As applications grow, this creates render-fetch-re-render loops, hidden waterfalls, and loading logic spread across components.</p>
<p>Suspense flips that model.</p>
<p>Instead of rendering first and fetching later, Suspense enables <code>Render-as-you-Fetch</code>. Data fetching can begin before React attempts to commit the UI, and rendering simply waits until the data is ready. The UI doesn’t guess when to show loading states. React coordinates it declaratively through Suspense boundaries.</p>
<p>With Suspense, you need to wrap the component that handles the asynchronous call.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770195686150/1160a43a-6be0-488a-aa19-315ac9f33985.png" alt="Suspense as Wrapper" class="image--center mx-auto" width="1137" height="472" loading="lazy"></p>
<p>Suspense can pause the rendering while the wrapped component is dealing with the promise. Suspense can show a fallback UI (it could be a loader, UI skeleton, and so on) until the promise is resolved (or rejected). Once the promise is resolved, Suspense replaces the fallback UI with the actual wrapped component baked with the data. No hard-coded logic, no extra state management is needed.</p>
<h2 id="heading-what-is-the-use-api-in-react">What is the <code>use()</code> API in React?</h2>
<p><code>use()</code> is an API introduced in React 19 that accepts a promise and returns its resolved value. If the promise hasn’t resolved yet, React doesn’t continue rendering. It suspends. If the promise fails, React throws an error. Both cases are handled declaratively by Suspense and Error Boundaries.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { use } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUser</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> fetch(<span class="hljs-string">"/api/user"</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json());
}

<span class="hljs-keyword">const</span> userPromise = fetchUser();

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Profile</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> user = use(userPromise);
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Welcome, {user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>;
}
</code></pre>
<p><strong>What’s important here:</strong></p>
<ul>
<li><p><code>use()</code> is called during render</p>
</li>
<li><p>If the promise is unresolved, rendering pauses</p>
</li>
<li><p>No <code>useEffect</code>, no loading state</p>
</li>
</ul>
<p><code>use()</code> is very powerful. It can read promises that depend on other promises.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> userPromise = fetch(<span class="hljs-string">"/api/user"</span>).then(<span class="hljs-function"><span class="hljs-params">r</span> =&gt;</span> r.json());

<span class="hljs-keyword">const</span> ordersPromise = userPromise.then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span>
  fetch(<span class="hljs-string">`/api/orders?userId=<span class="hljs-subst">${user.id}</span>`</span>).then(<span class="hljs-function"><span class="hljs-params">r</span> =&gt;</span> r.json())
);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Orders</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> orders = use(ordersPromise);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      {orders.map(o =&gt; <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{o.id}</span>&gt;</span>{o.title}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>)}
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here:</p>
<ul>
<li><p>Dependencies are expressed in data, not effects</p>
</li>
<li><p>Rendering is coordinated automatically (declaratively)</p>
</li>
</ul>
<p>The primary mental model is: this render is not allowed to complete without this data. It suspends.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> data = use(promise);
</code></pre>
<p>We need to use Suspense to handle this gap (when the promise hasn’t resolved yet) using a fallback UI, and then to continue rendering once the promise is resolved.</p>
<h2 id="heading-how-to-use-suspense-and-the-use-api-for-data-fetching">How to Use Suspense and the <code>use()</code> API for Data Fetching</h2>
<p>The <code>use()</code> API is what finally makes Suspense practical for data fetching. Before <code>use()</code>, Suspense could pause rendering, but React didn’t have a clean way to consume asynchronous data during render without hacks. Most examples relied on custom abstractions or libraries to bridge that gap. <code>use()</code> changed that by allowing React components to read async values directly during rendering.</p>
<p>When a component reads data using <code>use(promise)</code>, React treats that promise as a render dependency. If the promise hasn’t resolved yet, React pauses rendering at the nearest Suspense boundary. When it resolves, React retries rendering automatically, without manual state updates, effects, or conditional logic.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Suspense, use } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> userPromise = fetch(<span class="hljs-string">"/api/user"</span>).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res.json());

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Profile</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> user = use(userPromise);
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Welcome, {user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>;
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">p</span>&gt;</span>Loading profile...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}&gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">Profile</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>What happens here:</strong></p>
<ul>
<li><p>Profile tries to read userPromise</p>
</li>
<li><p>If the promise is unresolved, React pauses rendering</p>
</li>
<li><p>React renders the nearest Suspense fallback</p>
</li>
<li><p>When the promise resolves, React retries rendering automatically</p>
</li>
</ul>
<p>Here, there are no effects, no loading flags, and no manual re-rendering.</p>
<p>Now, let’s see all these in action together by rebuilding the same Dashboard app.</p>
<h2 id="heading-lets-build-the-dashboard-with-suspense-and-the-use-api">Let’s Build the Dashboard with Suspense and the <code>use()</code> API</h2>
<p>Now that we have a better understanding of Suspense and <code>use()</code>, let’s rewrite the same Dashboard application with it.</p>
<h3 id="heading-project-setup">Project Setup</h3>
<p>First, you’ll need to create a React project scaffolding using <a target="_blank" href="https://vite.dev/guide/#scaffolding-your-first-vite-project">Vite</a>. You can use the following command to create a Vite-based React project with modern toolings:</p>
<pre><code class="lang-bash">npx degit atapas/code-in-react-19<span class="hljs-comment">#main suspense-patterns</span>
</code></pre>
<p>This will create a React 19 project with TailwindCSS configured.</p>
<p>Now use the <code>npm install</code> command to install the dependencies. This will create the node_modules folder for you. At this point, the directory structure should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770281531136/c34dcf94-7142-4033-9445-53b08d010a5e.png" alt="React 19 Project Directory Structure" class="image--center mx-auto" width="384" height="752" loading="lazy"></p>
<h3 id="heading-api-services">API Services</h3>
<p>Now under <code>src/</code>, create a new folder called <code>api/</code>. Then create an <code>index.js</code> file under <code>src/app/</code> with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUser</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      resolve({ <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"Tapas"</span> });
    }, <span class="hljs-number">1500</span>);
  });
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchOrders</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      resolve([
          <span class="hljs-string">`Order A for user <span class="hljs-subst">${userId}</span>`</span>,
          <span class="hljs-string">`Order B for user <span class="hljs-subst">${userId}</span>`</span>
      ]);
    }, <span class="hljs-number">1500</span>);
  });
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchAnalytics</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      resolve({
        <span class="hljs-attr">revenue</span>: <span class="hljs-string">"$12,000"</span>,
        <span class="hljs-attr">growth</span>: <span class="hljs-string">"18%"</span>,
        userId
      });
    }, <span class="hljs-number">1500</span>);
  });
}
</code></pre>
<p>These are the same APIs we used before when constructing the dashboard with <code>useEffect</code>.</p>
<ul>
<li><p><code>fetchUser</code>: For fetching the user’s profile</p>
</li>
<li><p><code>fetchOrders</code>: For fetching the orders made by a user</p>
</li>
<li><p><code>fetchAnalytics</code>: For fetching the analytics data of a user</p>
</li>
</ul>
<h3 id="heading-create-a-centralised-user-resource">Create a Centralised User Resource</h3>
<p>Now, let’s create a centralised JavaScript utility file where we can create each of the promises by calling their respective fetch methods. It’s a good practice to handle all the fetch APIs and their promises from a single place, rather than keeping them scattered. The same utility can export the promises so that we can consume them in the components.</p>
<p>Create a <code>resources/</code> folder under <code>src/</code>. Create a file <code>userResource.js</code> file under <code>src/resources/</code> with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { fetchAnalytics, fetchOrders, fetchUser } <span class="hljs-keyword">from</span> <span class="hljs-string">"../api"</span>;

<span class="hljs-keyword">let</span> userPromise;
<span class="hljs-keyword">let</span> ordersPromise;
<span class="hljs-keyword">let</span> analyticsPromise;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUserResources</span>(<span class="hljs-params"></span>) </span>{
  userPromise = fetchUser();

  ordersPromise = userPromise.then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span>
    fetchOrders(user.id)
  );

  analyticsPromise = userPromise.then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span>
    fetchAnalytics(user.id)
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUserResources</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> {
    userPromise,
    ordersPromise,
    analyticsPromise
  };
}
</code></pre>
<p>Here, we export two functions:</p>
<ol>
<li><p>The <code>createUserResources()</code> creates all the promises and keeps them ready.</p>
</li>
<li><p>The <code>getUserResources()</code> returns all the promises we can consume later.</p>
</li>
</ol>
<p>Now, the question is, when will we create these promises? That is, where we will call the <code>createUserResources()</code> function? We should create these promises when the application starts up, and the <code>main.jsx</code> file would be the perfect place for that.</p>
<p>Open the main.jsx file, import <code>{createUserResources}</code>, and invoke it immediately.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App.jsx"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;

<span class="hljs-keyword">import</span> { createUserResources } <span class="hljs-keyword">from</span> <span class="hljs-string">"./resources/userResource.js"</span>;

createUserResources();

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>)).render(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>,
);
</code></pre>
<p>Great! Our data fetching APIs and the promises are ready. Let’s create the components where we’ll be using these promises.</p>
<h3 id="heading-create-individual-components">Create Individual Components</h3>
<p>We’ll create three components to compose the dashboard: Profile, Orders, and Analytics.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770297241100/91d9c21b-afcb-40ee-a73d-34a2be0f8cad.png" alt="Component Hierarchy" class="image--center mx-auto" width="1291" height="582" loading="lazy"></p>
<p>Let’s start with the Profile component. Create a folder <code>components/</code> under the <code>src/</code>. Now, create a <code>Profile.jsx</code> with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { use } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { getUserResources } <span class="hljs-keyword">from</span> <span class="hljs-string">"../resources/userResource"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Profile</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> { userPromise } = getUserResources();
    <span class="hljs-keyword">const</span> user = use(userPromise);
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>Welcome, {user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>;
}
</code></pre>
<p>Let’s break it down:</p>
<ul>
<li><p>We imported the <code>use()</code> from React, as we’ll be dealing with the use promise here to handle it and get the user name to render.</p>
</li>
<li><p>Next, we need the user promise. We have the <code>getUserResources()</code> function to get that, so we imported it.</p>
</li>
<li><p>Then, inside the Profile component, we destructured <code>userPromise</code> from the <code>getUserResources()</code> function.</p>
</li>
<li><p>After that, we passed the promise to the <code>use()</code>. We have learned that the <code>use()</code> API accepts a promise and returns the result when it is resolved. Until then, the passed-in promise itself will be returned.</p>
</li>
<li><p>Finally, we used the resolved <code>user</code> to extract the name property and render it.</p>
</li>
</ul>
<p>Simple, right? Let’s quickly create the Orders and Analytics components.</p>
<p>The Orders component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { use } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { getUserResources } <span class="hljs-keyword">from</span> <span class="hljs-string">"../resources/userResource"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Orders</span>(<span class="hljs-params"></span>) </span>{
   <span class="hljs-keyword">const</span> { ordersPromise } = getUserResources();
  <span class="hljs-keyword">const</span> orders = use(ordersPromise);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl mt-2"</span>&gt;</span>Orders<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
        {orders.map((o) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{o}</span>&gt;</span>{o}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<p>It has the same flow as the Profile component.</p>
<p>Now, let’s do the Analytics component:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { use } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { getUserResources } <span class="hljs-keyword">from</span> <span class="hljs-string">"../resources/userResource"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Analytics</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> { analyticsPromise } = getUserResources();
    <span class="hljs-keyword">const</span> analytics = use(analyticsPromise);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl mt-2"</span>&gt;</span>Analytics<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl"</span>&gt;</span>Revenue: {analytics.revenue}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl"</span>&gt;</span>Growth: {analytics.growth}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span></span>
    );
}
</code></pre>
<p>All three components are ready. Before we move further, let’s reflect once more on what we learned about <code>Suspense</code>.</p>
<p>Suspense wraps a component that deals with promises (async operations). Until the promise gets resolved, the Suspense holds the rendering and can show a fallback UI in the meantime. Once the promise gets resolved and we have the value, the fallback UI gets swapped with the actual component Suspense wrapped.</p>
<p>So, we have the ideal case now: wrapping the <code>&lt;Profile /&gt;</code>, <code>&lt;Orders/&gt;</code>, and <code>&lt;Analytics/&gt;</code> with the <code>&lt;Suspense&gt;…&lt;/Suspense&gt;</code> boundary to handle the promises and resolved data for each of the components.</p>
<p>Let’s do that, but aren’t we missing something? Yeah we are: the fallback UI. Let’s create it.</p>
<h3 id="heading-create-the-fallback-ui">Create the Fallback UI</h3>
<p>Now we’ll create three different fallback UI components. Create a file <code>Skeletons.jsx</code> under the <code>src/components/</code> with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ProfileSkeleton = <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl m-2"</span>&gt;</span>Loading user...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> OrdersSkeleton = <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl m-2"</span>&gt;</span>Loading orders...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> AnalyticsSkeleton = <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl m-2"</span>&gt;</span>Loading analytics...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
</code></pre>
<p>We now have a fallback skeleton UI for each of our components. These are very simple components that just render loading messages.</p>
<h3 id="heading-create-the-dashboard-component-with-suspense">Create the Dashboard Component with Suspense</h3>
<p>Now we have everything to make our Dashboard work. Create a <code>suspense/</code> folder under <code>src/</code>. Then create a <code>Dashboard.jsx</code> file under <code>src/suspense/</code> with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Suspense } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> Analytics <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Analytics"</span>;
<span class="hljs-keyword">import</span> Orders <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Orders"</span>;
<span class="hljs-keyword">import</span> Profile <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Profile"</span>;

<span class="hljs-keyword">import</span> {
    AnalyticsSkeleton,
    OrdersSkeleton,
    ProfileSkeleton,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Skeletons"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Dashboard</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"m-2"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-5xl mb-12"</span>&gt;</span>📊 Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">ProfileSkeleton</span> /&gt;</span>}&gt;
               <span class="hljs-tag">&lt;<span class="hljs-name">Profile</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">OrdersSkeleton</span> /&gt;</span>}&gt;
               <span class="hljs-tag">&lt;<span class="hljs-name">Orders</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">AnalyticsSkeleton</span> /&gt;</span>}&gt;
               <span class="hljs-tag">&lt;<span class="hljs-name">Analytics</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}
</code></pre>
<p>First, let me explain the code:</p>
<ul>
<li><p>We imported Suspense from React, all the components, and all the fallback UI components.</p>
</li>
<li><p>Then we rendered a static header and three suspense boundaries for each of the components. We wrapped Profile, Orders, and Analytics with Suspense, respectively. To handle the pending promise state, we have passed the individual skeleton component as the fallback to the suspense.</p>
</li>
</ul>
<p>How clean is this? If you scroll up and recheck our old implementation of the dashboard using useEffect and compare it with the one we created with suspense, the positive differences are clear.</p>
<ul>
<li><p>It’s declarative.</p>
</li>
<li><p>There’s less code, with the chance of fewer bugs</p>
</li>
<li><p>There’s no effect management and synchronisations</p>
</li>
<li><p>There’s no conditional JSX</p>
</li>
</ul>
<p>It’s a huge win 🏆.</p>
<h3 id="heading-run-the-dashboard-app">Run the Dashboard App</h3>
<p>To run the dashboard app, import the dashboard component in the <code>App.jsx</code> file and use it like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Dashboard <span class="hljs-keyword">from</span> <span class="hljs-string">"./suspense/Dashboard"</span>;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center justify-center gap-12"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Dashboard</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Next, open the terminal. Run the app using the <code>npm run dev</code> command. You get the same dashboard back, but it’s much improved:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770184122812/d8cd8d82-9f38-4ab6-b029-e2e68dbbd66a.png" alt="New dashboard" class="image--center mx-auto" width="806" height="919" loading="lazy"></p>
<ul>
<li><p>It loads the data of each of the sections independently.</p>
</li>
<li><p>Each of the sections shows the data loading indicator when the promise is pending.</p>
</li>
<li><p>It doesn’t block the entire UI.</p>
</li>
</ul>
<p>Suspense and <code>use()</code> together are very powerful. Now you have learned that powerful pattern end-to-end.</p>
<h2 id="heading-how-to-handle-error-scenarios-with-error-boundaries">How to Handle Error Scenarios with Error Boundaries</h2>
<p>This data fetching handbook wouldn’t be complete without talking about error scenarios and how to handle them. So far, we’ve spoken about only the happy path. But what if any of the promises are rejected? How do we handle that?</p>
<p>To understand this in depth, let’s reject one of the promises – say the Order promise. Open the <code>index.js</code> file under the <code>src/api/</code> folder and replace the <code>fetchOrder()</code> function with this updated code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchOrders</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// Simulate failure</span>
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Math</span>.random() &lt; <span class="hljs-number">0.5</span>) {
        reject(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to fetch orders"</span>));
      } <span class="hljs-keyword">else</span> {
        resolve([
          <span class="hljs-string">`Order A for user <span class="hljs-subst">${userId}</span>`</span>,
          <span class="hljs-string">`Order B for user <span class="hljs-subst">${userId}</span>`</span>
        ]);
      }
    }, <span class="hljs-number">1500</span>);
  });
}
</code></pre>
<p>Here, the changes are:</p>
<ul>
<li><p>We have simulated a failure by rejecting a promise.</p>
</li>
<li><p>The promise gets rejected randomly and throws an error with an error message.</p>
</li>
</ul>
<p>At this point, if you refresh the UI a few times, you’ll randomly get a blank broken UI with the error message logged into the browser console. This isn’t ideal. It kills the UX of the app.</p>
<p>A better way of handling would be to show the error message on the UI and provide a way to retry and check if the user can recover from the error.</p>
<p>This is where <code>Error Boundary</code> comes in.</p>
<h3 id="heading-error-boundary">Error Boundary</h3>
<p>Error Boundaries in React exist for a simple reason: Errors are inevitable, and we must handle them gracefully. There could be:</p>
<ul>
<li><p>Network requests fail</p>
</li>
<li><p>Data is malformed</p>
</li>
<li><p>The assumptions break</p>
</li>
</ul>
<p>Without boundaries, a single tiny rendering error can crash the entire React tree. Error Boundaries provide React with a structured way to handle failures.</p>
<p>Technically, an Error Boundary is a component that catches errors thrown during rendering. When an error occurs, React stops rendering the subtree and renders a fallback UI instead.</p>
<p>Let’s now create an Error Boundary. Create a file called <code>ErrorBoundary.jsx</code> under <code>src/components</code> with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { createUserResources } <span class="hljs-keyword">from</span> <span class="hljs-string">"../resources/userResource"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ErrorBoundary</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  state = { <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> };

  <span class="hljs-keyword">static</span> getDerivedStateFromError(error) {
    <span class="hljs-keyword">return</span> { error };
  }

  handleRetry = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span> });
    createUserResources();
  };

  render() {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.state.error) {
      <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"border border-red-700 rounded p-1"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl"</span>&gt;</span>{this.state.error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> 
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-orange-400 rounded-xl p-1 text-black cursor-pointer"</span> 
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{this.handleRetry}</span>&gt;</span>
            Retry
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      );
    }

    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.props.children;
  }
}
</code></pre>
<p>Now, let’s understand what’s going on in the code above:</p>
<ul>
<li><p>This is a class component that inherits from <code>React.Component</code>. That’s because Error Boundaries must use class lifecycle methods, which are not available in function components.</p>
</li>
<li><p>The component keeps track of whether an error has occurred. <code>state = { error: null }</code> means everything is rendering normally. When an error happens, this state will store the error object.</p>
</li>
<li><p>The <code>static getDerivedStateFromError()</code> is a special lifecycle method. React automatically calls it when a child component throws an error during render.</p>
</li>
<li><p>The <code>handleRetry()</code> method resets the error state back to null. It calls the <code>createUserResources()</code> to reinitialise the async resources.</p>
</li>
<li><p>In the <code>render()</code> method, if an error exists, render a fallback UI, show the error message, and provide an ability to retry the error using a retry button. If no error exists, render the <code>children</code> normally. The Error Boundary becomes invisible when everything works without an error. The fallback UI also can be an external component that we can pass as a prop to the Error Boundary.</p>
</li>
</ul>
<p>If you’re interested in diving deep into the <code>Error Boundary</code> pattern and want to learn various use cases of it, <a target="_blank" href="https://www.youtube.com/watch?v=0qxF4jb-eUg">here is a dedicated video</a> you can check out.</p>
<h3 id="heading-suspense-and-error-boundary">Suspense and Error Boundary</h3>
<p>Next, we’ll now use the Error Boundary to wrap each of the Suspense boundaries so that if an error originated from any of those, it can be managed. Open the <code>Dashboard.jsx</code> file and wrap each of the Suspense boundaries with the <code>ErrorBoundary</code> component as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Suspense } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> Analytics <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Analytics"</span>;
<span class="hljs-keyword">import</span> ErrorBoundary <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/ErrorBoundary"</span>;
<span class="hljs-keyword">import</span> Orders <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Orders"</span>;
<span class="hljs-keyword">import</span> Profile <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Profile"</span>;
<span class="hljs-keyword">import</span> {
    AnalyticsSkeleton,
    OrdersSkeleton,
    ProfileSkeleton,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Skeletons"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Dashboard</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"m-2"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-5xl mb-12"</span>&gt;</span>📊 Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">ErrorBoundary</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">ProfileSkeleton</span> /&gt;</span>}&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">Profile</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ErrorBoundary</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">ErrorBoundary</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">OrdersSkeleton</span> /&gt;</span>}&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">Orders</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ErrorBoundary</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">ErrorBoundary</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">AnalyticsSkeleton</span> /&gt;</span>}&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">Analytics</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ErrorBoundary</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}
</code></pre>
<p>That’s it. Now, access the dashboard on the browser. Whenever the order promise rejects, we’ll get the fallback error UI from the error boundary. Note, the remaining UI isn’t broken and rendered successfully. The partial failure of the UI is also recoverable, as we have provided a retry button to attempt to revive that portion. It provides a great UX.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770301723655/36fbba52-805b-4a23-8d18-9516a413160e.png" alt="Error Boundary with Suspense" class="image--center mx-auto" width="644" height="689" loading="lazy"></p>
<p>This is how the Suspense boundary, the <code>use()</code> API, and the Error Boundary work together to help you write scalable React code that can be maintained very easily in the future. I hope you found it helpful. All the source code used in this handbook is in the <a target="_blank" href="https://github.com/tapascript/15-days-of-react-design-patterns/tree/main/day-16">tapaScript GitHub Repository</a>.</p>
<h2 id="heading-learn-from-the-15-days-of-react-design-patterns">Learn from the 15 Days of React Design Patterns</h2>
<p>I have some great news for you: after my 40 days of JavaScript initiative, I have now completed a brand new initiative called <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">15 Days of React Design Patterns</a> (with Bonus Episodes).</p>
<p>If you enjoyed learning from this handbook, I’m sure you’ll love this series, featuring the 15+ most important React design patterns. Check it out, subscribe, and get it for free:</p>
<p><a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1770087890778/c89e0666-898d-448c-9d2c-443788fd4413.png" alt="15 days of React Design Patterns" class="image--center mx-auto" width="1562" height="894" loading="lazy"></a></p>
<h2 id="heading-before-we-end">Before We End…</h2>
<p>That’s all! I hope you found this insightful.</p>
<p><a target="_blank" href="https://github.com/tapascript/15-days-of-react-design-patterns/tree/main/day-03/compound-components-patterns">Let’s connect:</a></p>
<ul>
<li><p>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</p>
</li>
<li><p>Check out my courses, <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRw2Fwwjt6cPC_tk5vcSICCu">40 Days of JavaScript</a>, <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">15 Days of React Design Patterns</a>, and <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRwT8Msc4H3_CP5Tf8MqqqVZ">Thinking in Debugging</a>.</p>
</li>
<li><p>Follow on <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Join my <a target="_blank" href="https://discord.gg/zHHXx4vc2H">Discord Server</a>, and let’s learn together.</p>
</li>
<li><p>Follow my work on <a target="_blank" href="https://github.com/tapascript">GitHub</a>.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Why is Debugging Hard? How to Develop an Effective Debugging Mindset ]]>
                </title>
                <description>
                    <![CDATA[ For years, developers have been told that coding was their primary job. They were encouraged to write clean code, learn tools, understand frameworks, and ship features faster. But in the actual world of Software Engineering, especially in product-foc... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/why-is-debugging-hard-how-to-develop-an-effective-debugging-mindset/</link>
                <guid isPermaLink="false">6966f02a4a96d46c5a7981c0</guid>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ problem solving skills ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Wed, 14 Jan 2026 01:23:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768328774505/f27dbe5d-8a5d-4826-a641-446a537c2d5c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>For years, developers have been told that coding was their primary job. They were encouraged to write clean code, learn tools, understand frameworks, and ship features faster.</p>
<p>But in the actual world of Software Engineering, especially in product-focused companies and customer-facing systems, coding is only half the work. The other half is just as important, and it’s the process called <code>Debugging</code>.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-debugging">What is Debugging?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-this-guide">Why this Guide?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-is-debugging-hard">Why is Debugging Hard?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-mental-model">What is a Mental Model?</a></p>
</li>
<li><p><a target="_blank" href="heading-the-debugging-mental-model-framework">The Debugging Mental Model Framework</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-bug-found">Step 1: Bug Found</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-define-the-facts">Step 2: Define the Facts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-identify-your-assumptions">Step 3: Identify Your Assumptions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-form-a-hypothesis">Step 4: Form a Hypothesis</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-verify-the-hypothesis">Step 5: Verify the Hypothesis</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-putting-everything-together">Putting Everything Together</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-apply-the-debugging-mindset-framework-to-code">How to Apply the Debugging Mindset Framework to Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-debugging-mindset-framework-is-tool-agnostic">The Debugging Mindset Framework is Tool Agnostic</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-whats-next">What’s Next?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-before-we-end">Before We End...</a></p>
</li>
</ol>
<h2 id="heading-what-is-debugging">What is Debugging?</h2>
<p>Debugging is the practice and methodology developers use to identify issues or problems within a system. Usually, an issue or an unexpected behaviour/problem is known as a <code>bug</code>. The process of <code>debugging</code>, then, is to identify the bug – followed by an attempt to eliminate it or fix it.</p>
<p>Debugging becomes necessary when assumptions break, customers report issues, products behave unexpectedly, or metrics go red. It’s the practice that keeps a software product reliable, teams calm, and users trusting what you build.</p>
<p>Yet, strangely, debugging rarely gets the same respect and attention as coding. It’s often treated as a necessary evil, something that you “figure out along the way” rather than a skill to be learned deliberately.</p>
<h2 id="heading-why-this-guide">Why this Guide?</h2>
<p>The general neglect of basic debugging skills is catching up with us.</p>
<p>Today, with AI tools, generating code is easier than it has ever been. You can create boilerplate, scaffold components, write functions, establish relations, and even build entire applications in minutes.</p>
<p>But when things go wrong (as they always do), AI doesn’t sit with your product logs, customer complaints, partial failures, and confusing edge cases. Debugging still falls to the human to tackle, and that’s where many devs struggle.</p>
<p>Over the last two decades, I’ve build many products and worked with many developers across experience levels. I’ve noticed a consistent pattern: most debugging failures are not tool failures. They are thinking failures. People jump to fixes too quickly. They start guessing. They panic. They change code without understanding why it broke in the first place.</p>
<p>That’s why I am writing this debugging mindset tutorial. This guide will NOT:</p>
<ul>
<li><p>Teach you tools</p>
</li>
<li><p>Share tricks</p>
</li>
</ul>
<p>But it will enable you to think things through when things break.</p>
<p>Alongside this article, I’m also creating a free YouTube course called “<a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRwT8Msc4H3_CP5Tf8MqqqVZ">Thinking in Debugging</a>”. It’s a practical series on how professional developers approach debugging in JavaScript, React, CSS, and real-world frontend systems. Here is the first session from the course:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/CnQ2WN601b4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>In modern software development, writing code gets you started. But debugging is what makes you reliable. Reliability is the most important trait both an engineer and a product must have.</p>
<h2 id="heading-why-is-debugging-hard">Why is Debugging Hard?</h2>
<p>Here’s how most developers debug code:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768114186304/962dfd2a-dfdf-431b-8940-f6ede25ea49d.png" alt="Debugging Hard - Bad Mindset" class="image--center mx-auto" width="2316" height="1116" loading="lazy"></p>
<ul>
<li><p>Something is broken</p>
</li>
<li><p>Let me change the line</p>
</li>
<li><p>Let’s refresh (wishing the error would go away)</p>
</li>
<li><p>Hmm… still broken!</p>
</li>
<li><p>Now, let me add a console.log()</p>
</li>
<li><p>Let me refresh again (Ah, this time it may…)</p>
</li>
<li><p>Ok, looks like this time it worked!</p>
</li>
</ul>
<p>This is reaction-based debugging. It’s like throwing a stone in the dark or finding a needle in a haystack. It feels busy, it sounds productive, but it’s mostly guessing. And guessing doesn’t scale in programming.</p>
<p>This approach and the guessing mindset make debugging hard for developers. The lack of a methodology and solid approach makes many devs feel helpless and frustrated, which makes the process feel much more difficult than coding.</p>
<p>This is why we need a different mental model, a defined skillset to master the art of debugging. Let’s understand what a mental model is and what the debugger’s mindset should be.</p>
<h2 id="heading-what-is-a-mental-model">What is a Mental Model?</h2>
<p>A <code>mental model</code> drives us to think and make decisions. Our brain is at the centre of it. It collects information, processes it, and helps us make those decisions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768114359730/a9647a21-4638-45d2-9bd0-87906cc642a8.png" alt="The Mental Model" class="image--center mx-auto" width="2410" height="1048" loading="lazy"></p>
<p>When we encounter an issue in programming and we need to find the root cause to fix it, we need to rely on various information and inputs to make logical decisions. We need to create a mental model.</p>
<p>Good debuggers don’t fight bugs. They <code>investigate</code> them. They don’t start with the mindset of “How do I fix this?”. They start with, “Why must this bug exist?” This one question changes everything.</p>
<p>When you ask about the existence of a bug, you go back to the history to collect information about the code, its changes, and its flow. Then, you feed this information through a “mental model” to make decisions that lead you to the fix.</p>
<p>Now, let’s learn about this debugging mental model. This isn’t merely a tool – this is a way of thinking.</p>
<h2 id="heading-the-debugging-mental-model-framework">The Debugging Mental Model Framework</h2>
<p>Before we take a deep dive into the debugging mental model, the key idea is that you never touch the fix until the hypothesis survives reality.</p>
<p>So in this context, what does hypothesis mean?</p>
<blockquote>
<p>A Hypothesis is an idea that is suggested as the possible explanation for something but has not yet been found to be true or correct.</p>
</blockquote>
<p>With this, let’s get started understanding the debugging mental model framework. It consists of multiple steps or phases that you must go through to find the root cause of a bug and fix it. Once you understand the framework, we’ll apply it to an actual bug in some JavaScript code to make our learning practical.</p>
<p>Let’s Go.</p>
<h3 id="heading-step-1-bug-found">Step 1: Bug Found</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768114826708/553936d2-3640-47ec-b032-3d485292fe5f.png" alt="Bug Found" class="image--center mx-auto" width="652" height="394" loading="lazy"></p>
<p>The first step is identifying the bug. You or someone else (QA, Customer, and so on) has found that something is wrong. It could be a UI glitch, the wrong output, slow performance, or anything else that is not working as promised and expected.</p>
<p>At this stage, the unexpected behaviour should be documented with enough proof, like logs, screenshots, and steps, for anyone else to reproduce the bug easily. As a developer, don’t panic that something isn’t working as expected. Also, don’t code yet.</p>
<h3 id="heading-step-2-define-the-facts">Step 2: Define the Facts</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768114900772/3ef0b5bf-6b42-4ecc-8a5f-4756eafd617e.png" alt="Define The facts" class="image--center mx-auto" width="880" height="420" loading="lazy"></p>
<p>Once the bug is found and reported, the next stage is defining or establishing the facts. Facts are things that you can prove, not guesses. For example:</p>
<ul>
<li><p>This component renders twice.</p>
</li>
<li><p>This API returns correct data.</p>
</li>
<li><p>This function receives a string, not a number.</p>
</li>
</ul>
<p>Here are a few examples of guesses, but not facts:</p>
<ul>
<li><p>React is acting weird.</p>
</li>
<li><p>The API must be slow.</p>
</li>
<li><p>This worked yesterday.</p>
</li>
<li><p>It works on my machine 😁.</p>
</li>
</ul>
<p>Defining facts means writing down only what you can prove. What actually happened? What did the user see? What error was thrown? What data was received? Facts are observable, repeatable, and not an outcome of your emotions.</p>
<p>Defining the facts also empowers you to be aware of the code flow and business cases. So this phase is your opportunity to carefully review the code, requirements, and learn about it, irrespective of who wrote it. Once you know the facts, note them down.</p>
<h3 id="heading-step-3-identify-your-assumptions">Step 3: Identify Your Assumptions</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768115009148/f7268ddb-2f95-49f8-ab0b-c7029d0668a4.png" alt="Assumptions Made" class="image--center mx-auto" width="1130" height="360" loading="lazy"></p>
<p>Every bug is based on a broken assumption. Assumptions often feel harmless because they usually work, until they don’t. Examples:</p>
<ul>
<li><p>I assumed this was a number.</p>
</li>
<li><p>I assumed useEffect would run only once.</p>
</li>
<li><p>I assumed the state updates immediately.</p>
</li>
<li><p>I assumed the API always returns data.</p>
</li>
</ul>
<p>Here, the goal is to surface those hidden beliefs. Ask yourself, what must be the actual reason for this code to work as expected? The moment your answer is an assumption, you’re off track. You then recollect, think carefully, stop blaming the system, and start questioning the mental model.</p>
<p>Most bugs are not caused by bad code, but by unverified assumptions.</p>
<h3 id="heading-step-4-form-a-hypothesis">Step 4: Form a Hypothesis</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768115062165/33dc8ca4-0bf6-4452-8033-d0ca54fbae1d.png" alt="Form a Hypothesis" class="image--center mx-auto" width="1094" height="380" loading="lazy"></p>
<p>This is where the actual debugging of the code begins. Once the facts are clear and assumptions are visible, the debugging makes its way forward.</p>
<p>Now you’ll need to form a hypothesis. A hypothesis is a simple cause-and-effect statement: If this assumption is wrong, then the behaviour makes sense. If not, provide a fix.</p>
<p>You may have logs from customers and the best debugging tools from management. But without a good hypothesis, logs become noise and tools become unnecessary. With a good hypothesis, debugging stops being reactive and becomes investigative.</p>
<h3 id="heading-step-5-verify-the-hypothesis">Step 5: Verify the Hypothesis</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768115157162/3f3e60a7-2711-40d1-bff1-c937684ff777.png" alt="Verify Hypothesis" class="image--center mx-auto" width="1504" height="1052" loading="lazy"></p>
<p>A hypothesis has no value without meeting reality. You’ll need to verify if your hypothesis is realistic. How do you do that? This is where you use the tools with a purpose. A console.log() statement, a breakpoint, and a network inspection are some of the actions you can perform to answer the question: Is my hypothesis true or false?</p>
<p>If the hypothesis fails, you discard it and move to the next. That’s progress, not failure. On the other hand, if the hypothesis holds, the fix should become clear. You’re no longer making code changes to make the bug disappear suddenly – rather, you’re correcting the root cause.</p>
<h3 id="heading-putting-everything-together">Putting Everything Together</h3>
<p>As we now understand each of the phases, let’s visualise them together and see the bigger picture. I would encourage you to take a pause here and look carefully at each of the boxes below. Now, try processing your understanding from whatever you learned so far about them. Promise yourself that you will apply these to your day-to-day development journey.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768189936681/70e16db4-6ae9-4426-9a37-df3c7333e366.png" alt="Putting Everything Together - the debugging process" class="image--center mx-auto" width="1864" height="1116" loading="lazy"></p>
<p>Sounds good? Theoretically, it does. But you may have doubts about how all these strategies can work practically. Now, we will apply these to a problem statement and see the practicality of it.</p>
<h2 id="heading-how-to-apply-the-debugging-mindset-framework-to-code">How to Apply the Debugging Mindset Framework to Code</h2>
<p>Let’s take an example of a bug that has confused millions of developers across the globe 😀.</p>
<p><strong>Here’s the code</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUser</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">let</span> user;

  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
    user = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Alex"</span> };
  }, <span class="hljs-number">1000</span>);

  <span class="hljs-keyword">return</span> user;
}

<span class="hljs-built_in">console</span>.log(fetchUser());
</code></pre>
<p><strong>The Output</strong>: It logs <code>undefined</code> to the browser’s log.</p>
<p><strong>The Bug</strong>: I Set the User… Why is it <code>undefined</code>?</p>
<p>Now, let’s apply the debugging mental model framework.</p>
<h3 id="heading-step-1-bug-found-1">Step 1: Bug Found</h3>
<p>Here, the observation is that the function returns undefined. There are no errors in the console. The code looks correct. The scariest bugs are the ones that don’t throw errors.</p>
<h3 id="heading-step-2-define-the-facts-1">Step 2: Define the Facts</h3>
<p>So, what are the provable facts you see here?</p>
<ul>
<li><p>fetchUser() runs.</p>
</li>
<li><p>setTimeout is scheduled.</p>
</li>
<li><p>return user runs.</p>
</li>
<li><p>The user is undefined at return time.</p>
</li>
</ul>
<p>Remember that facts are the things you can prove, not what you believe.</p>
<h3 id="heading-step-3-identify-your-assumptions-1">Step 3: Identify Your Assumptions</h3>
<p>Now, ask yourself, “What am I assuming here?”. Here are a few common beginner assumptions for this case:</p>
<ul>
<li><p>JavaScript runs line-by-line synchronously.</p>
</li>
<li><p>The setTimeout blocks execution.</p>
</li>
<li><p>Code waits for 1 second.</p>
</li>
<li><p>The user variable is assigned before the return from the function.</p>
</li>
</ul>
<p>Most async bugs come from the assumptions about execution time.</p>
<h3 id="heading-step-4-form-a-hypothesis-1">Step 4: Form a Hypothesis</h3>
<p>Next, we need to form a hypothesis to introduce structured thinking. The function returns undefined. If our assumptions were right, the user variable should have the assigned value. It seems that there’s something wrong with the assumptions.</p>
<ul>
<li><p>Does the setTimeout really block execution?</p>
</li>
<li><p>Does the code really wait for 1 second?</p>
</li>
<li><p>If JavaScript doesn’t wait for setTimeout, then <code>return user</code> will execute before the assignment. This is how the user variable could be undefined. It seems like we’re dealing with the <code>Async</code> operation here. This is the aha moment – that’s our hypothesis.</p>
</li>
</ul>
<p>We aren’t fixing anything yet. We’re predicting behaviour.</p>
<h3 id="heading-step-5-verify-or-kill-the-hypothesis">Step 5: Verify or Kill the Hypothesis</h3>
<p>Now, we need to verify our hypothesis. Let’s use console.log() for that. We’ll add two logs, one inside the setTimeout before assigning the user variable value, and the other just before returning the user from the function.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUser</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">let</span> user;

  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Inside timeout"</span>);
    user = { <span class="hljs-attr">name</span>: <span class="hljs-string">"Alex"</span> };
  }, <span class="hljs-number">1000</span>);

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Before return:"</span>, user);
  <span class="hljs-keyword">return</span> user;
}

<span class="hljs-built_in">console</span>.log(fetchUser());
</code></pre>
<p>Execute the code, and here are the observations:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768115561817/989b2bfa-1a66-4c82-a746-f89537b5dc15.png" alt="Output - JavaScript" class="image--center mx-auto" width="790" height="360" loading="lazy"></p>
<ul>
<li><p>“Before return:” logs first.</p>
</li>
<li><p>“Inside timeout” logs later.</p>
</li>
</ul>
<p>This means that our hypothesis survives the reality. We proved that debugging is not guessing – it’s about ordering the execution time correctly in our heads.</p>
<h3 id="heading-step-6-fix-with-the-proof">Step 6: Fix With the Proof</h3>
<p>Now our fix becomes obvious, not a guess or magic. If we want the user’s value to be logged instead of undefined, we can fix it in multiple ways, like using a callback function or a promise object.</p>
<ul>
<li>With a callback: Define a callback function that gets called after the time expires. The callback function takes the value as a parameter and assign to the user before logging it to the console.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUser</span>(<span class="hljs-params">callback</span>) </span>{
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
    callback({ <span class="hljs-attr">name</span>: <span class="hljs-string">"Alex"</span> });
  }, <span class="hljs-number">1000</span>);
}

fetchUser(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(user));
</code></pre>
<ul>
<li>With Promise Object: Alternatively, we can use the Promise object. The promise resolves after 1 second, and we log the user details with the help of the <code>.then()</code> handler method.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUser</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      resolve({ <span class="hljs-attr">name</span>: <span class="hljs-string">"Alex"</span> });
    }, <span class="hljs-number">1000</span>);
  });
}

fetchUser().then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(user));
</code></pre>
<p>Let’s now visualise all the stages together with respect to the problem we discussed:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768208236822/475899fd-7ea1-41f2-a97b-0c4bcc51c775.png" alt="debugging mental model with JS" class="image--center mx-auto" width="1749" height="959" loading="lazy"></p>
<h2 id="heading-the-debugging-mindset-framework-is-tool-agnostic">The Debugging Mindset Framework is Tool Agnostic</h2>
<p>Note that the debugging mental model teaches you how to observe, think through, and justify your beliefs to find the root cause of the issue. Once confirmed, you need to use your programming language knowledge and coding skills to implement the fix. The debugging mindset or mental model framework itself is technology and tool agnostic.</p>
<p>It doesn’t belong to JavaScript, React, Python, or any specific tool. The need for facts, assumptions, hypotheses, and verification exists in every technology stack. Today, you might be debugging a React component. Tomorrow it could be CSS layout, backend logic, or a memory leak. The same thinking applies. This is why experienced developers adapt more quickly to new programming languages, frameworks, or tools. They carry this mindset with them.</p>
<h2 id="heading-whats-next">What’s Next?</h2>
<p>Technologies evolve, frameworks come and go, but the debugging mental model framework remains constant. So focus on that. Have a mindset to own up to the issues you’ve found in a software product. No development is bug-free. You create bugs sometimes, so you should just proudly own them. And now, you should have the mindset to confidently fix them.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1574065446149/BqXCWWpte.png" alt="Debugging Detective" width="619" height="783" loading="lazy"></p>
<p>I would like to invite you to join my free course <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRwT8Msc4H3_CP5Tf8MqqqVZ">Thinking in Debugging</a>. In it, we won’t only set up this mental model, but also realise it by debugging JavaScript, React, and CSS with DevTools, Debugger, and Profiler.</p>
<h2 id="heading-before-we-end"><strong>Before We End...</strong></h2>
<p>That’s all! I hope you found this article insightful.</p>
<p><a target="_blank" href="https://github.com/tapascript/15-days-of-react-design-patterns/tree/main/day-03/compound-components-patterns">Let’s connect:</a></p>
<ul>
<li><p>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</p>
</li>
<li><p>Check out my courses, <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRw2Fwwjt6cPC_tk5vcSICCu">40 Days of JavaScript</a> and <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">15 Days of React Design Patterns</a>.</p>
</li>
<li><p>Follow on <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Join my <a target="_blank" href="https://discord.gg/zHHXx4vc2H">Discord Server</a>, and let’s learn together.</p>
</li>
<li><p>Follow my work on <a target="_blank" href="https://github.com/tapascript">GitHub</a>.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use the Optimistic UI Pattern with the useOptimistic() Hook in React ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever clicked a Like icon on a social media app and noticed the count jumps instantly? The colour of the icon changes at the same time, even before the server finishes the action. Now imagine you hit the same Like button, but it takes its swe... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-the-optimistic-ui-pattern-with-the-useoptimistic-hook-in-react/</link>
                <guid isPermaLink="false">693c5d28a2bfa1537f407a65</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Fri, 12 Dec 2025 18:21:28 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1765561440350/c3546e6c-8b23-476a-86d4-b63fd2cb9f6c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever clicked a <code>Like</code> icon on a social media app and noticed the count jumps instantly? The colour of the icon changes at the same time, even before the server finishes the action.</p>
<p>Now imagine you hit the same Like button, but it takes its sweet time in making the server call, performing the DB updates, and getting you the response back to update the state of the Like button.</p>
<p>Which experience would you like the most? You are most likely to select the first scenario. We all love “instant feedback”. The magic of instant feedback is powered by a pattern called the <code>Optimistic UI Pattern</code>.</p>
<p>In this article, we will uncover:</p>
<ul>
<li><p>What does Optimistic UI really mean?</p>
</li>
<li><p>Why does it massively improve the user experience?</p>
</li>
<li><p>How does React 19’s new useOptimistic() hook make it easier than ever?</p>
</li>
<li><p>How to implement a real-world scenario using the Optimistic Pattern</p>
</li>
<li><p>A bunch of use cases where you will be able to use this pattern.</p>
</li>
</ul>
<p>By the end, you will be proactively thinking of using this design pattern to improve the UX of your project.</p>
<p>This article is also available as a video tutorial as part of the <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">15 Days of React Design Patterns</a> <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">initiative</a>. Please check it out.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/x03yX-yNxas" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-optimistic-ui">What is Optimistic UI</a>?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-does-it-work-under-the-hood">How Does it Work Under the Hood?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-an-optimistic-like-button">How to Build an Optimistic Like Button</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-pitfalls-and-anti-patterns">The Pitfalls and Anti-Patterns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-15-days-of-react-design-patterns">15 Days of React Design Patterns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-before-we-end">Before We End...</a></p>
</li>
</ol>
<h2 id="heading-what-is-optimistic-ui">What is Optimistic UI?</h2>
<p><code>Optimistic UI</code> (also known as optimistic updates) is a pattern that helps you update the UI immediately, assuming the server operation will succeed, and if it later fails, you roll back the UI to the correct state.</p>
<p>Instead of waiting for the round-trip of the client request, database write, server response, and then the UI render, the UI just updates instantly. This dramatically increases what’s called the <code>perceived speed</code>. The user of the application perceives the UI update as instant – but the actual operation may take place in the background.</p>
<h3 id="heading-without-an-optimistic-update">Without an Optimistic Update:</h3>
<p>If you’re not using the optimistic pattern, it’s just a traditional client-server mechanism, where:</p>
<ul>
<li><p>At the client side, a user interacts with a UI element.</p>
</li>
<li><p>An <a target="_blank" href="https://www.youtube.com/watch?v=WQdCffdPPKI">async call</a> (request) is made to the server.</p>
</li>
<li><p>The server processes the request and may make DB updates.</p>
</li>
<li><p>On a successful case, the server sends back the response to the client.</p>
</li>
<li><p>The client updates the relevant UI.</p>
</li>
<li><p>In an error case, the server sends back the error response to the client.</p>
</li>
<li><p>The client informs the user about the error.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765334108586/aabd3f16-b175-4b1d-ae33-94f33e1b894a.png" alt="Without an Optimistic Update" class="image--center mx-auto" width="1240" height="704" loading="lazy"></p>
<p>In this case, the user has to wait for the success/failure of the request to perceive any change after their interaction. This wait is neither uniform nor optimal. It may vary based on the network speed, network latency, and deployment strategies of the application.</p>
<h3 id="heading-with-an-optimistic-update">With an Optimistic Update:</h3>
<p>When you’re using an optimistic update, here’s how things go:</p>
<ul>
<li><p>At the client side, a user interacts with a UI element.</p>
</li>
<li><p>The UI gets updated instantly, and the user perceives the feedback immediately.</p>
</li>
<li><p>In parallel, in the background, the client initiates the server call.</p>
</li>
<li><p>The server processes the request and may make DB updates.</p>
</li>
<li><p>On a successful case, the server doesn’t do anything else, as the UI has been updated already, assuming this call will succeed.</p>
</li>
<li><p>In an error case, the server sends back the error response to the client.</p>
</li>
<li><p>The client rolls back the eager, optimistic UI update it made.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765334174203/e8bef9ba-28b6-45e0-8f22-0fc1468e3219.png" alt="With an Optimistic Update" class="image--center mx-auto" width="1189" height="892" loading="lazy"></p>
<p>In this case, the user doesn’t wait for the server round-trip to complete before the UI is updated. It’s much faster, assuming that, in most cases, the parallel server call will succeed.</p>
<p>With this comparison, we can now understand why Optimistic Updates matter in modern UI.</p>
<ul>
<li><p>It improves perceived speed</p>
</li>
<li><p>It keeps users engaged</p>
</li>
<li><p>It eliminates the awkward feelings like “Did my click work?”</p>
</li>
</ul>
<p>And so on. Optimistic updates are critical for real-time feeling features like chat messages, likes, comments, cart updates, poll votes, collaborative editing, and more. Even AI-driven apps that take time to respond benefit from optimistic placeholders like “Thinking…”, “Sending…” and so on.</p>
<h2 id="heading-how-does-it-work-under-the-hood">How Does it Work Under the Hood?</h2>
<p>Under the hood, there are actually two states:</p>
<ol>
<li><p>The Actual State: This is the actual source of truth. This data should be in sync with the server.</p>
</li>
<li><p>The Optimistic State: This is temporary and instantly shown to the user.</p>
</li>
</ol>
<p>When the server request succeeds, do nothing. Your optimistic state is now correct. If the server request fails, perform a rollback, and return UI the actual state.</p>
<p>React 19 introduced a built-in hook to help with this pattern called <code>useOptimistic()</code> . In the next section, we will take a deep dive into it with code and working internals.</p>
<h3 id="heading-the-useoptimistic-hook-in-react-19">The <code>useOptimistic()</code> Hook in React 19</h3>
<p><code>useOptimistic()</code> is a React hook introduced in React 19 to help with optimistic updates. The syntax and usage of the hook go like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [optimisticState, addOptimistic] = useOptimistic(state, updateFn);
</code></pre>
<p>When an async action is underway, the <code>useOptimistic()</code> hook allows you to show different states.</p>
<p>It accepts:</p>
<ol>
<li><p><strong>currentState</strong>: your real source of truth (useState, Redux, server state, and so on)</p>
</li>
<li><p><strong>updateFn</strong>: a pure function that says how to compute the optimistic value</p>
</li>
</ol>
<p>It returns:</p>
<ol>
<li><p><strong>optimisticState</strong>: the temporary UI state</p>
</li>
<li><p><strong>addOptimisticUpdate(input)</strong>: function you call to apply immediate updates</p>
</li>
</ol>
<p>Take a look at the picture below. It shows the relationship between the current state and the optimistic state clearly:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765434835916/249e71eb-bba6-4b98-951a-feb397dc36e2.png" alt="Anatomy" class="image--center mx-auto" width="1744" height="781" loading="lazy"></p>
<p>Here’s what’s going on there:</p>
<ol>
<li><p>We pass the current state and an updater function to the <code>useOptimistic</code> hook.</p>
</li>
<li><p>The updater function takes the current state and a user input to compute and return the next optimistic state.</p>
</li>
<li><p>The input to the updater function is supplied using the <code>addOptimistic(input)</code> function.</p>
</li>
<li><p>Finally, the optimistic state value is used in the component.</p>
</li>
</ol>
<p>Let’s now build something exciting using this hook to understand its internals better.</p>
<h2 id="heading-how-to-build-an-optimistic-like-button">How to Build an Optimistic Like Button</h2>
<p>We will be building the Like button functionality optimistically. The flow will be like this:</p>
<ul>
<li><p>The user clicks on the Like button.</p>
</li>
<li><p>We update the Like button’s state immediately and optimistically.</p>
</li>
<li><p>In parallel, we send the server call to persist the value into the DB (we will simulate it)</p>
</li>
<li><p>Then we handle any error scenarios.</p>
</li>
</ul>
<p>First, let’s simulate a network call to the server using JavaScript’s Promise object and the <code>setTimeout()</code> web API:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// simulate a network call to the Server</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendLikeToServer</span>(<span class="hljs-params">postId</span>) </span>{
    <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">r</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(r, <span class="hljs-number">700</span>));

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Math</span>.random() &lt; <span class="hljs-number">0.2</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Network failed"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Sent a like for the post id <span class="hljs-subst">${postId}</span>`</span>);
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span> };
}
</code></pre>
<p>The <code>sendLikeToServer</code> function takes a post ID as a parameter and simulates a fake network call using a Promise and a delay of 700 ms. It pretends to submit a request to the server to persist a post’s likes value.</p>
<p>To make it a bit more realistic, we have created a random error. The function will throw an error randomly so that we can understand the rollback scenario as well.</p>
<p>Next, we will create the real source of truth, the actual state for the Like count:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [likes, setLikes] = useState(initialLikes);
</code></pre>
<p>Then, create the optimistic state value with the <code>useOptimistic()</code> hook:</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> [optimisticLikes, addOptimisticLike] = useOptimistic(
        likes, <span class="hljs-function">(<span class="hljs-params">currentLikes, delta</span>) =&gt;</span> currentLikes + delta);
</code></pre>
<p>Let’s understand this declaration well:</p>
<ul>
<li><p>We have passed the actual state value (likes) and the updater function to the <code>useOptimistic()</code> hook.</p>
</li>
<li><p>Take a look at the updater function, <code>(currentLikes, delta) =&gt; currentLikes + delta</code>. It’s an arrow function that gets the current like value and a delta. It returns the sum of the current like value and the delta. The return value logic is your own business logic. For incrementing the like count, it makes sense to increase the current like value by a delta value (of 1).</p>
</li>
<li><p>Now, the question is, how do we get this delta value? Who passes it? That’s where the return values of <code>useOptimistic()</code> come in handy. The <code>addOptimisticLike</code> is a function through which we can pass that delta value. How? Let’s take a look.</p>
</li>
</ul>
<p>When someone clicks on the Like button, we need to handle the click event and increase the like count value. So here is a <code>handleLike()</code> function which does that:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleLike = <span class="hljs-keyword">async</span> () =&gt; {
        addOptimisticLike(<span class="hljs-number">1</span>);
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">await</span> sendLikeToServer(postId);
            setLikes(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> prev + <span class="hljs-number">1</span>);
        } <span class="hljs-keyword">catch</span> (err) {
            <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Like failed:"</span>, err);
            setLikes(<span class="hljs-function">(<span class="hljs-params">s</span>) =&gt;</span> s); 
        }
};
</code></pre>
<p>A lot is happening here:</p>
<ul>
<li><p>We call the <code>addOptimisticLike()</code> function with a delta value of 1. This call will ensure that the updater function <code>(currentLikes, delta) =&gt; currentLikes + delta</code> of the <code>useOptimistic()</code> will be called. The return value will be set to the optimistic state, that is, <code>optimisticLikes</code>.</p>
</li>
<li><p>This optimistic state value we use in the JSX. So we can see the increased like count immediately.</p>
</li>
<li><p>Then we make the fake server call, and also update the actual state, provided the server call was successful.</p>
</li>
<li><p>In case of an error, the control goes into the catch-block, where we roll back the likes value to the previous one. This will also sync the optimistic state’s value with a rollback.</p>
</li>
</ul>
<p>Here is the complete code of the <code>LikeButton</code> component:</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">import</span> { startTransition, useOptimistic, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-comment">// simulate a network call to the Server</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendLikeToServer</span>(<span class="hljs-params">postId</span>) </span>{
    <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">r</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(r, <span class="hljs-number">700</span>));

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Math</span>.random() &lt; <span class="hljs-number">0.2</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Network failed"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Sent a like for the post id <span class="hljs-subst">${postId}</span>`</span>);
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span> };
}

<span class="hljs-comment">// The Like Button Component</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">LikeButton</span>(<span class="hljs-params">{ postId, initialLikes = <span class="hljs-number">0</span> }</span>) </span>{
    <span class="hljs-comment">// the "real" source of truth for likes (committed)</span>
    <span class="hljs-keyword">const</span> [likes, setLikes] = useState(initialLikes);
    <span class="hljs-comment">// optimistic state and updater function</span>
    <span class="hljs-keyword">const</span> [optimisticLikes, addOptimisticLike] = useOptimistic(
        likes,
        <span class="hljs-function">(<span class="hljs-params">currentLikes, delta</span>) =&gt;</span> currentLikes + delta
    );

    <span class="hljs-keyword">const</span> handleLike = <span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-comment">// 1) Apply optimistic change *immediately*</span>
        addOptimisticLike(<span class="hljs-number">1</span>);

        <span class="hljs-comment">// 2) Start server call in low priority to avoid blocking UI</span>

        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">await</span> sendLikeToServer(postId);
            <span class="hljs-comment">// On success, commit the real state update:</span>
            <span class="hljs-comment">// IMPORTANT: update the real state so optimistic snapshot eventually matches</span>
            setLikes(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> prev + <span class="hljs-number">1</span>);
        } <span class="hljs-keyword">catch</span> (err) {
            <span class="hljs-comment">// On error, rollback the real state (or trigger a refetch)</span>
            <span class="hljs-comment">// Because we never incremented likes (real), just leave likes unchanged</span>
            <span class="hljs-comment">// But we should show an error to user:</span>
            <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Like failed:"</span>, err);
            <span class="hljs-comment">// Optionally: show toast or set an error state</span>
            <span class="hljs-comment">// And — to force the optimistic view to refresh and reflect real state,</span>
            <span class="hljs-comment">// call setLikes to current value</span>
            setLikes(<span class="hljs-function">(<span class="hljs-params">s</span>) =&gt;</span> s); <span class="hljs-comment">// no-op but will cause optimistic to reflect the</span>
                                <span class="hljs-comment">// committed value Or you can trigger a re-fetch of the </span>
                                <span class="hljs-comment">// post state</span>
        }
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleLike}</span>&gt;</span>❤️ {optimisticLikes}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> startTransition(async () =&gt; handleLike())}&gt;
                ❤️ {optimisticLikes}
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}
</code></pre>
<p>Have you noticed that we have wrapped the <code>handleLike()</code> call with the <code>startTransition</code>?</p>
<p>Without this, React gives us a warning:</p>
<blockquote>
<p>“An optimistic state update occurred outside a transition or action.”</p>
</blockquote>
<p>This is because optimistic updates are <strong>low-priority visual updates</strong>, not critical ones.</p>
<p>Using <code>startTransition()</code> ensures that:</p>
<ul>
<li><p>React doesn’t block rendering</p>
</li>
<li><p>We do not get the warning</p>
</li>
<li><p>We get a smooth, optimistic experience</p>
</li>
</ul>
<p>The transitions are part of React’s concurrency model that helps us improve the performance of React applications. If you are interested in learning various performance optimisation techniques, <a target="_blank" href="https://www.youtube.com/watch?v=G8Mk6lsSOcw">here is a two-part guide for you</a>.</p>
<h2 id="heading-the-pitfalls-and-anti-patterns">The Pitfalls and Anti-Patterns</h2>
<p>With any design pattern, we need to be aware of possible pitfalls, misuses, and anti-patterns. Here are a few things you should be aware of:</p>
<ul>
<li><p>Don’t assume that the server call will be successful. Network failure will happen, and you need to have a way to roll back. Rollback is the heart of optimistic UI. Omitting the rollback logic will cause adverse consequences.</p>
</li>
<li><p>Don’t try hiding the bad UX behind optimistic updates. The Optimistic UI is not a fix or replacement for poor designs.</p>
</li>
<li><p>Don’t perform any expensive work in optimistic updates. Keep the optimistic updater function lean, pure, and fast.</p>
</li>
</ul>
<h2 id="heading-15-days-of-react-design-patterns"><strong>15 Days of React Design Patterns</strong></h2>
<p>I have some great news for you: after my <em>40 days of the JavaScript</em> initiative, I have now started a brand new initiative called <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">15 Days of React Design Patterns</a>.</p>
<p>If you enjoyed learning from this article, I am sure you will love this series, featuring the 15+ most important React design patterns. Check it out and join for FREE:</p>
<p><a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765439781697/751c2051-5dc2-4a88-bcc2-037f6ce0e91e.png" alt="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC" class="image--center mx-auto" width="1612" height="850" loading="lazy"></a></p>
<h2 id="heading-before-we-end"><strong>Before We End...</strong></h2>
<p>That’s all! I hope you found this article insightful. You can find all the source code used in this tutorial on the <a target="_blank" href="https://github.com/tapascript/15-days-of-react-design-patterns/tree/main/day-08">tapaScript GitHub</a>.</p>
<p><a target="_blank" href="https://github.com/tapascript/15-days-of-react-design-patterns/tree/main/day-03/compound-components-patterns">Let’s connect:</a></p>
<ul>
<li><p>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</p>
</li>
<li><p>Grab the <a target="_blank" href="https://www.tapascript.io/books/react-hooks-cheatsheet">React Hooks Cheatsheet</a>.</p>
</li>
<li><p>Follow on <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Join my <a target="_blank" href="https://discord.gg/zHHXx4vc2H">Discord Server</a>, and let’s learn together.</p>
</li>
<li><p>Subscribe to my fortnightly newsletter, <a target="_blank" href="https://tapascript.substack.com/subscribe?utm_medium=fcc">The Commit Log</a>.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is TOON? How Token-Oriented Object Notation Could Change How AI Sees Data ]]>
                </title>
                <description>
                    <![CDATA[ JSON, or JavaScript Object Notation, was popularized by Douglas Crockford in early 2000. Since then, there’s been no looking back. JSON has become the standardized data exchange format between client and server technologies. JSON was built for humans... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-toon-how-token-oriented-object-notation-could-change-how-ai-sees-data/</link>
                <guid isPermaLink="false">6915f8076f343530b3b31c7b</guid>
                
                    <category>
                        <![CDATA[ llm ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ json ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Thu, 13 Nov 2025 15:23:51 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762978794293/e75f145b-a418-458e-8a41-12fe3add0107.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><code>JSON</code>, or JavaScript Object Notation, was popularized by Douglas Crockford in early 2000. Since then, there’s been no looking back. JSON has become the standardized data exchange format between client and server technologies.</p>
<p>JSON was built for humans. It’s readable, accessible, and universal for APIs to consume data or return responses. But in the modern era of AI, a downside of JSON has really come to light: it’s quite verbose.</p>
<p>Every brace, every quote, and every repeated key consumes tokens. If you spend time building apps that talk to large language models (LLMs), you’ll likely know that tokens are the currency of LLM interactions. The more tokens, the more costly your AI solution is going to be.</p>
<p>Now, there is a new kid in town called <code>TOON</code> (Token-Oriented Object Notation). It promises to enable LLMs to talk to structured data more efficiently, intelligently, and cost-effectively.</p>
<p>This article is the result of my curiosity in exploring TOON. I wanted to learn why it’s trending, how it works, and how you can use it today in your JavaScript/TypeScript and Python projects. I hope you find this equally exciting as I do.</p>
<p>You can find all the source code used in this article in <a target="_blank" href="https://github.com/tapascript/toon-and-json">this GitHub Repository</a>.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-toon">What is Toon?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-is-toon-important-now">Why is TOON Important Now?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-json-vs-toon-learn-with-examples">JSON vs TOON - Learn With Examples</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-toon-with-javascript-typescript">How to Use TOON With JavaScript / TypeScript</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-toon-with-python">How to Use Toon With Python?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-hold-on-json-might-still-be-betterin-many-cases">Hold On, JSON Might Still Be Better(In Many Cases)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-future-of-toon">The Future of TOON</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-before-we-end">Before We End…</a></p>
</li>
</ol>
<h2 id="heading-what-is-toon">What is Toon?</h2>
<p>TOON is a new data serialization format designed with a code objective:</p>
<blockquote>
<p>Reduce the number of tokens when exchanging structured data with language models.</p>
</blockquote>
<p>While JSON uses verbose syntax with braces, quotes, and commas, TOON relies on a token-efficient tabular style, which is much closer to how LLMs naturally understand structured data.</p>
<p>Let’s make a quick comparison between JSON and TOON:</p>
<p>Here is some JSON with a <code>users</code> array that contains information about two users (two objects):</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"users"</span>: [
    { <span class="hljs-attr">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-attr">"role"</span>: <span class="hljs-string">"admin"</span> },
    { <span class="hljs-attr">"id"</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Bob"</span>, <span class="hljs-attr">"role"</span>: <span class="hljs-string">"user"</span> }
  ]
}
</code></pre>
<p>If you wanted to represent the same data in TOON, it would look like this:</p>
<pre><code class="lang-json">users[<span class="hljs-number">2</span>]{id,name,role}:
  <span class="hljs-number">1</span>,Alice,admin
  <span class="hljs-number">2</span>,Bob,user
</code></pre>
<p>Did you notice the differences?</p>
<ul>
<li><p>No quotes, braces, or colons in TOON.</p>
</li>
<li><p>The <code>users[2]{id,name,role}:</code> declares an array of two objects with the fields id, name, and role.</p>
</li>
<li><p>The lines below are simply the data rows.</p>
</li>
</ul>
<p>You can see that TOON visibly reduced the token usage by 30-50%, depending on the data shape.</p>
<h2 id="heading-why-is-toon-important-now">Why is TOON Important Now?</h2>
<p>LLMs like GPT, Gemini, and Claude are token-based systems. Each word, symbol, or chunk costs tokens for input and output. So, if you’re preparing an LLM with structured data input/output like this:</p>
<pre><code class="lang-json">{ <span class="hljs-attr">"products"</span>: [ ... <span class="hljs-number">300</span>, <span class="hljs-string">"items"</span> ... ] }
</code></pre>
<p>You might waste thousands of tokens in quotes, braces, colons, and repeated keys. TOON solves that by focusing on a compact yet structured representation.</p>
<p>Some of the key benefits of TOON are:</p>
<ul>
<li><p>30-50% fewer tokens for uniform data sets.</p>
</li>
<li><p>It has less syntactic clutter, which makes it easier for LLMs to reason about.</p>
</li>
<li><p>It can be nested as we do with JSON.</p>
</li>
<li><p>Works well with languages like Python, Go, Rust, and JavaScript.</p>
</li>
</ul>
<p>TOON is a great augmentation to JSON, especially for AI projects, LLMs, and data-heavy prompts. It may not replace JSON entirely, but it’s suitable for use cases where JSON is considered heavyweight for data exchange.</p>
<h2 id="heading-json-vs-toon-learn-with-examples">JSON vs TOON – Learn With Examples</h2>
<p>Now that you have a basic idea of what TOON does and why it’s helpful, let’s look at some of the most used JSON structures and their equivalent representation in TOON.</p>
<h3 id="heading-1-a-simple-object">1. A Simple Object</h3>
<p>Here’s how you’d represent an object with JSON:</p>
<pre><code class="lang-json">{ <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-attr">"age"</span>: <span class="hljs-number">30</span>, <span class="hljs-attr">"city"</span>: <span class="hljs-string">"Bengaluru"</span> }
</code></pre>
<p>And here’s how it works with TOON:</p>
<pre><code class="lang-json">name: Alice
age: <span class="hljs-number">30</span>
city: Bengaluru
</code></pre>
<h3 id="heading-2-array-of-values">2. Array of Values</h3>
<p>With JSON:</p>
<pre><code class="lang-json">{ <span class="hljs-attr">"colors"</span>: [<span class="hljs-string">"red"</span>, <span class="hljs-string">"green"</span>, <span class="hljs-string">"blue"</span>] }
</code></pre>
<p>With TOON:</p>
<pre><code class="lang-json">colors[<span class="hljs-number">3</span>]: red,green,blue
</code></pre>
<h3 id="heading-3-array-of-objects">3. Array of Objects</h3>
<p>With JSON:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"users"</span>: [
    { <span class="hljs-attr">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Alice"</span> },
    { <span class="hljs-attr">"id"</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Bob"</span> }
  ]
}
</code></pre>
<p>With TOON:</p>
<pre><code class="lang-json">users[<span class="hljs-number">2</span>]{id,name}:
  <span class="hljs-number">1</span>,Alice
  <span class="hljs-number">2</span>,Bob
</code></pre>
<p>Here, <code>users[2]{id,name}</code> represents the schema, and the lines following it contain the actual data rows.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762968459600/03584141-37ae-429d-a999-99ffb93acdcc.png" alt="TOON Schema" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-4-nested-objects">4. Nested Objects</h3>
<p>With JSON:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"user"</span>: {
    <span class="hljs-attr">"id"</span>: <span class="hljs-number">1</span>,
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Alice"</span>,
    <span class="hljs-attr">"profile"</span>: { <span class="hljs-attr">"age"</span>: <span class="hljs-number">30</span>, <span class="hljs-attr">"city"</span>: <span class="hljs-string">"Bengaluru"</span> }
  }
}
</code></pre>
<p>With TOON:</p>
<pre><code class="lang-json">user:
  id: <span class="hljs-number">1</span>
  name: Alice
  profile:
    age: <span class="hljs-number">30</span>
    city: Bengaluru
</code></pre>
<p>Indentation represents nesting. It’s almost YAML-like, but it’s still structured.</p>
<h3 id="heading-5-array-of-objects-with-nested-fields">5. Array of Objects With Nested Fields</h3>
<p>With JSON:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"teams"</span>: [
    {
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Team Alpha"</span>,
      <span class="hljs-attr">"members"</span>: [
        { <span class="hljs-attr">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Alice"</span> },
        { <span class="hljs-attr">"id"</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Bob"</span> }
      ]
    }
  ]
}
</code></pre>
<p>With TOON:</p>
<pre><code class="lang-json">teams[<span class="hljs-number">1</span>]:
  - name: Team Alpha
    members[<span class="hljs-number">2</span>]{id,name}:
      <span class="hljs-number">1</span>,Alice
      <span class="hljs-number">2</span>,Bob
</code></pre>
<p>This is still perfectly understandable, and much smaller than the JSON format.</p>
<p>Now that you know a bit about TOON syntax, let’s see how to use it with different programming languages.</p>
<h2 id="heading-how-to-use-toon-with-javascript-typescript">How to Use TOON With JavaScript / TypeScript</h2>
<p>In most cases, TOON is not meant to be handwritten. Most TOON data will be generated automatically by software, or you’ll need to encode existing data (say, JSON data) into the TOON format.</p>
<p>And there’s good news – <a target="_blank" href="https://github.com/toon-format">TOON</a> already has an official NPM package that you can use in your JavaScript/TypeScript project to convert your JSON data to TOON and vice versa.</p>
<p>Install it using the following command:</p>
<pre><code class="lang-bash">npm install @toon-format/toon <span class="hljs-comment"># Or yarn add, pnpm install, etc</span>
</code></pre>
<p>The easiest way to create TOON code is by converting JSON to TOON. You can use the <code>encode()</code> method from the above-mentioned NPM package:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { encode } <span class="hljs-keyword">from</span> <span class="hljs-string">"@toon-format/toon"</span>;

<span class="hljs-keyword">const</span> data = {
  <span class="hljs-attr">users</span>: [
    { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">"admin"</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"Bob"</span>, <span class="hljs-attr">role</span>: <span class="hljs-string">"user"</span> },
  ],
};

<span class="hljs-keyword">const</span> toonString = encode(data);
<span class="hljs-built_in">console</span>.log(toonString);
</code></pre>
<p>Output:</p>
<pre><code class="lang-json">users[<span class="hljs-number">2</span>]{id,name,role}:
  <span class="hljs-number">1</span>,Alice,admin
  <span class="hljs-number">2</span>,Bob,user
</code></pre>
<p>To do the reverse (TOON =&gt; JSON), you need to use the <code>decode()</code> method:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { decode } <span class="hljs-keyword">from</span> <span class="hljs-string">"@toon-format/toon"</span>;

<span class="hljs-keyword">const</span> toonString = <span class="hljs-string">`
users[2]{id,name,role}:
  1,Alice,admin
  2,Bob,user
`</span>;

<span class="hljs-keyword">const</span> jsonObject = decode(toonString);
<span class="hljs-built_in">console</span>.log(jsonObject);
</code></pre>
<p>Output:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"users"</span>: [
    { <span class="hljs-attr">"id"</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-attr">"role"</span>: <span class="hljs-string">"admin"</span> },
    { <span class="hljs-attr">"id"</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Bob"</span>, <span class="hljs-attr">"role"</span>: <span class="hljs-string">"user"</span> }
  ]
}
</code></pre>
<p>You can check out <a target="_blank" href="https://codesandbox.io/p/sandbox/javascript-forked-n4zsww">this sandbox</a> and try out a few encoding and decoding examples.</p>
<h2 id="heading-how-to-use-toon-with-python">How to Use Toon With Python</h2>
<p>Using TOON in Python projects is as straightforward as it was with JavaScript/TypeScript. There are Python packages that can encode JSON data to TOON and decode it back to JSON. The <code>python-toon</code> package is the most famous one in recent days.</p>
<p>First, open your terminal and install the <code>python-toon</code> package:</p>
<pre><code class="lang-bash">pip install python-toon
</code></pre>
<p>Note that if you’re in a virtual environment, you’ll need to activate it first:</p>
<pre><code class="lang-bash">python -m venv venv
<span class="hljs-built_in">source</span> venv/bin/activate
pip install python-toon
</code></pre>
<p>That’s it! Now you’re all set to use the methods to encode and decode your data to and from TOON. First, let’s encode JSON data to TOON using Python:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> toon <span class="hljs-keyword">import</span> encode

<span class="hljs-comment"># A channel object</span>
channel = {<span class="hljs-string">"name"</span>: <span class="hljs-string">"tapaScript"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"type"</span>: <span class="hljs-string">"education"</span>}
toon_output = encode(channel)
print(toon_output)
</code></pre>
<p>Output:</p>
<pre><code class="lang-json">name: tapaScript
age: <span class="hljs-number">2</span>
type: education
</code></pre>
<p>Similarly, we can decode TOON back to JSON:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> toon <span class="hljs-keyword">import</span> decode

toon_string = <span class="hljs-string">"""
name: tapaScript
age: 2
type: education
"""</span>

python_struct = decode(toon_string)
print(python_struct)
</code></pre>
<p>Output:</p>
<pre><code class="lang-json">{<span class="hljs-attr">"name"</span>: <span class="hljs-string">"tapaScript"</span>, <span class="hljs-attr">"age"</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">"type"</span>: <span class="hljs-string">"education"</span>}
</code></pre>
<h2 id="heading-hold-on-json-might-still-be-better-in-many-cases">Hold On, JSON Might Still Be Better (In Many Cases)</h2>
<p>Let’s make it clear that TOON is NOT a universal replacement for JSON. In fact, you should still prefer JSON in many cases, such as when:</p>
<ul>
<li><p>Your data is deeply nested.</p>
</li>
<li><p>Your data is irregular (for example, varying object shapes).</p>
</li>
<li><p>Your application needs strict schema validations or type enforcement.</p>
</li>
<li><p>NON-AI use cases where JSON still stands out and does its job perfectly.</p>
</li>
</ul>
<p>A hybrid approach may even work better. Keep JSON for your application’s data exchange format with APIs, but convert to TOON when it comes to sending data to LLMs.</p>
<h2 id="heading-the-future-of-toon">The Future of TOON</h2>
<p>TOON, though in its infancy, is still getting a lot of attention from the developer community. Its early traction is making it unavoidable to talk about.</p>
<p>TOON has already been explored for:</p>
<ul>
<li><p>Less token overhead for structured training data to fine-tune LLMs.</p>
</li>
<li><p>Compact data exchange in Agent frameworks.</p>
</li>
<li><p>Faster data serialization and deserialization between the MCP and AI workflow engines.</p>
</li>
<li><p>With Serverless AI APIs, where cost and speed matter a lot.</p>
</li>
</ul>
<p>Just as JSON has been a standard for the Web’s data exchange, TOON may soon be standardized for AI data interchange. So next time you craft a prompt or pass structured data to an AI model, try it in the TOON format. You may notice the model gets faster and cheaper.</p>
<h2 id="heading-before-we-end">Before We End…</h2>
<p>That’s all! I hope you found this article insightful.</p>
<p>Let’s connect:</p>
<ul>
<li><p>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</p>
</li>
<li><p>Check out my FREE courses, <a target="_blank" href="https://www.tapascript.io/courses/40-days-javascript">40 Days of JavaScript</a> and <a target="_blank" href="https://www.tapascript.io/courses/react-design-patterns">15 Days of React Design Patterns</a>.</p>
</li>
<li><p>Follow on <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Join my <a target="_blank" href="https://discord.gg/zHHXx4vc2H">Discord Server</a>, and let’s learn together.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use the Compound Components Pattern in React: Prop Soup to Flexible UIs ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever opened React project source code and wondered why things are so messy? Have you ever tried adding a feature to a React component created by someone else and felt that you needed to rewrite it? Have you felt nightmarish in tackling state... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/compound-components-pattern-in-react/</link>
                <guid isPermaLink="false">68e70e0ecfc3d2834515166c</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Thu, 09 Oct 2025 01:21:18 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759972853846/49e605c8-be15-44a4-9fc6-283be0cc0e4c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever opened React project source code and wondered why things are so messy? Have you ever tried adding a feature to a React component created by someone else and felt that you needed to rewrite it? Have you felt nightmarish in tackling state and props for a component and its children?</p>
<p>If you happen to shout out “Yes!” to the above, you’re not alone. It’s a common feeling among many React developers across the globe. But React itself is not responsible for any of these issues. These situations arise because of code smells like:</p>
<ul>
<li><p>Props drilled six levels down.</p>
</li>
<li><p>A single bloated component doing everything.</p>
</li>
<li><p>Logic that’s duplicated across different components.</p>
</li>
<li><p>Careless rendering (and re-rendering) causing performance issues.</p>
</li>
</ul>
<p>A <code>Code Smell</code> doesn’t mean broken code. Rather, it’s an indication that the code may work now, but is difficult to maintain, reuse, scale, and much harder to debug.</p>
<p>And that’s exactly where we need to use <code>Design Patterns</code>. They’re well-tested solutions to the various code smell problems that developers have been encountering for decades. When you know how to use them well, you achieve a clean, maintainable codebase that is easy to enhance, debug, and scale.</p>
<p>Today, we will take a deep dive into one of the most prominent design patterns in React called the <code>Compound Components Pattern</code>. This pattern saves React developers from passing a long list of props and helps build composable user interface components.</p>
<p>This is going to be a complete hands-on tutorial. So get your favourite code editor ready, and let’s get started. This article is also available as a video tutorial as part of the <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">15 Days of React Design Patterns</a> initiative. Please check it out.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/LglWulOqh6k" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-react-19-code-set-up">React 19 Code Set Up</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-messy-modal-component">A Messy Modal Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-problems-with-this-messy-modal-component">The Problems with this messy Modal Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-compound-components-pattern">The Compound Components Pattern</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-a-modal-component-using-the-compound-components-pattern">How to Build a Modal Component using the Compound Components Pattern</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-didnt-we-create-separate-files-for-the-subcomponents">Why Didn’t We Create Separate Files for the SubComponents?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-the-modal-component">How to Use the Modal Component</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-an-accordion-component-using-the-compound-components-pattern">How to build an Accordion Component using the Compound Components Pattern</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-add-the-accordion-to-the-modal">Add the Accordion to the Modal</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-the-use-cases">The Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-pitfalls-and-anti-patterns">The Pitfalls and Anti-Patterns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-15-days-of-react-patterns">15 Days of React Design Patterns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-before-we-end">Before We End...</a></p>
</li>
</ol>
<h2 id="heading-react-19-code-set-up">React 19 Code Set Up</h2>
<p>The best way to understand how to apply a design pattern is by refactoring messy code with code smells to improve it to cleaner code. So let’s set up a coding ground so that we can start putting in our messy code first, and then go about applying the design pattern to it.</p>
<p>Note: you can find all the source code used in this tutorial on the <a target="_blank" href="https://github.com/tapascript/15-days-of-react-design-patterns/tree/main/day-03/compound-components-patterns">tapaScript GitHub</a>. Feel free to follow along with it side by side.</p>
<p>Also, make sure you have Node.js installed (preferably v18+). You can check it out by typing this command on your terminal/command prompt:</p>
<pre><code class="lang-bash">node -v
</code></pre>
<p>If you get an output with the installed Node.js version, you are all set. Otherwise, just download and install Node.js from <a target="_blank" href="https://nodejs.org/en/download">here</a>.</p>
<p>Now, run this command in your terminal to create a React 19 project scaffolding:</p>
<pre><code class="lang-bash">npx degit atapas/code-in-react-19<span class="hljs-comment">#main compound-components-pattern</span>
</code></pre>
<p>It will create a folder called <code>compound-components-pattern</code> with the Vite-based React project files under it. Now, change the directory using this command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> compound-components-pattern
</code></pre>
<p>Then install the dependencies using this command:</p>
<pre><code class="lang-bash">npm install <span class="hljs-comment">## Or, yarn install, or pnpm install, etc,</span>
</code></pre>
<p>Now, you can import the project folder into your favourite code editor (I use VS Code).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759478983493/692ac0f9-4780-4d60-bc72-55f27b9a6074.png" alt="Code Scaffolding" class="image--center mx-auto" width="481" height="552" loading="lazy"></p>
<p>Finally, to start the project locally, use the following command:</p>
<pre><code class="lang-bash">npm run dev <span class="hljs-comment">## Or, yarn dev, or pnpm dev</span>
</code></pre>
<p>Now the project should be running locally and should be accessible on the default URL, <a target="_blank" href="http://localhost:5173"><code>http://localhost:5173</code></a>. You can access the URL in your browser. Now we’re all set to start coding.</p>
<h2 id="heading-a-messy-modal-component">A Messy Modal Component</h2>
<p>Let’s get started by creating a Modal component. Start by creating a directory called <code>messy</code> under the <code>src/</code> directory. Now, create a file called <code>Modal.jsx</code> under <code>src/messy/</code> with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Modal</span>(<span class="hljs-params">{ title, body, primaryAction, secondaryAction }</span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-backdrop"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-container"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-header"</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-body"</span>&gt;</span>{body}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-footer"</span>&gt;</span>
                    {secondaryAction}
                    {primaryAction}
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Modal;
</code></pre>
<p>This is a simple React implementation of a modal component that accepts a title, body, and a couple of actions as props to render them as a modal.</p>
<ul>
<li><p>The <code>title</code>: The header title of the modal.</p>
</li>
<li><p>The <code>body</code>: The modal content.</p>
</li>
<li><p>The <code>primaryAction</code>: An action button like delete, create, save, and so on to place in the footer section of the modal.</p>
</li>
<li><p>The <code>secondaryAction</code>: An action button like cancel, close, and so on to place in the footer section of the modal.</p>
</li>
</ul>
<p>Next, open the <code>App.jsx</code> file and replace the existing code with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Modal <span class="hljs-keyword">from</span> <span class="hljs-string">"./messy/Modal"</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Modal</span>
                <span class="hljs-attr">title</span>=<span class="hljs-string">"Delete Account"</span>
                <span class="hljs-attr">body</span>=<span class="hljs-string">"Are you sure you want to delete your account?"</span>
                <span class="hljs-attr">primaryAction</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">button</span>&gt;</span>Delete<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>}
                secondaryAction={<span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Cancel<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>} /&gt;
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Here, we have imported the <code>Modal</code> component and used it by passing its props values. Go to the browser tab and access the app’s URL. You should see the modal appearing like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759409687600/825901e9-5b38-49a7-8d7d-74a0867f6a01.png" alt="messy modal without style" class="image--center mx-auto" width="2172" height="1312" loading="lazy"></p>
<p>Well, as it doesn’t look like a traditional modal with a backdrop and all, so let’s fix that using CSS. Open the <code>App.css</code> and paste the following CSS styles into it and save it:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.modal-backdrop</span> {
    <span class="hljs-attribute">position</span>: fixed;
    <span class="hljs-attribute">inset</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.5</span>);
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">align-items</span>: center;
}
<span class="hljs-selector-class">.modal-container</span> {
    <span class="hljs-attribute">background</span>: white;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">8px</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">1rem</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">400px</span>;
    <span class="hljs-attribute">position</span>: relative;
}
<span class="hljs-selector-class">.modal-header</span> {
    <span class="hljs-attribute">font-weight</span>: bold;
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">1rem</span>;
}
<span class="hljs-selector-class">.modal-footer</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">justify-content</span>: flex-end;
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">0.5rem</span>;
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">1rem</span>;
}
<span class="hljs-selector-class">.modal-close</span> {
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">top</span>: <span class="hljs-number">8px</span>;
    <span class="hljs-attribute">right</span>: <span class="hljs-number">8px</span>;
    <span class="hljs-attribute">background</span>: none;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2rem</span>;
}
</code></pre>
<p>Great! Now you have a cool-looking modal dialog asking for your confirmation to delete your account.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759409736382/ceaaa23e-26d3-4d7d-93ed-ae83aa69b421.png" alt="Messy Modal with style" class="image--center mx-auto" width="2170" height="1314" loading="lazy"></p>
<h2 id="heading-the-problems-with-this-messy-modal-component">The Problems with This Messy Modal Component</h2>
<p>Question for you: What problems do you think this modal implementation might have?</p>
<p>Let’s find the answers:</p>
<ol>
<li><p><code>Lack of Flexibility</code>: The modal has a rigid structure that dictates exactly what it renders. What if you want a modal without a title? Or a modal with a custom layout? Or more than two action buttons? You need to write additional logic and pass additional props every time you think of enhancing the modal for another use case. These changes in the component will bring maintainability issues and increase code smell.</p>
</li>
<li><p><code>Mixed Responsibilities</code>: The modal tries to do multiple things. It handles both layout and content. This violates the separation of concerns principle that we learn from other design patterns, such as the <a target="_blank" href="https://www.youtube.com/watch?v=1UHbhikwg-s">Container-Presenter Pattern</a>.</p>
</li>
<li><p><code>Hard Reusability</code>: The modal lacks reusability due to its rigidness. Right now, if you want a modal with this:</p>
<pre><code class="lang-javascript"> &lt;h2&gt;Something Wrong!&lt;/h2&gt;
 <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"warning.png"</span> /&gt;</span></span>
 <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Something went wrong. please see the logs for more details.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre>
<p> You can not reuse this component, and you will end up creating a new one.</p>
</li>
<li><p><code>Poor Scalability</code>: The modal component is not scalable. Think, for example, if you’re creating a component library and you end up creating multiple modal instances like ConfirmationModal, InfoModal, FormModal, ImageModal, and so on. It would be a huge ding on the scalability of that component library to create and maintain every new version of the modal.</p>
</li>
<li><p><code>Hard to Test</code>: This modal implementation is hard to test due to its tight coupling with props.</p>
</li>
</ol>
<p>With these issues in mind, let’s welcome the compound components pattern and see how it can help us solve them.</p>
<h2 id="heading-the-compound-components-pattern">The Compound Components Pattern</h2>
<p><code>Compound Components Pattern</code> in React is a design pattern where a parent component works together with its child components to share an implicit state and behaviour. Instead of passing a long list of props, the parent manages the state and exposes flexible child components (&lt;Modal.Header&gt;, &lt;Modal.Body&gt;, &lt;Modal.Footer&gt;, and so on) so that consumers can compose the UI naturally, just like using native HTML elements.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759409949714/8144535d-c0f3-4ae7-bd8d-ab93fe7bf6c2.png" alt="Compound Components Pattern Diagram" class="image--center mx-auto" width="2572" height="1238" loading="lazy"></p>
<p>Think of Compound Composition Pattern like LEGO blocks.</p>
<ul>
<li><p>The parent component is like the LEGO base plate.</p>
</li>
<li><p>The child components are the LEGO blocks (door, window, roof, and so on).</p>
</li>
<li><p>You don’t pass any props to the base plate, saying, <em>“add a door here, add a window there.”</em> Instead, you simply place the pieces where you want them.</p>
</li>
<li><p>The base plate (parent) still provides the rules and structure (studs, alignment, stability), but you get the flexibility to assemble your model however you like.</p>
</li>
</ul>
<p>Got it? That’s the power of compound components. It’s a flexible composition with a shared state/behaviour underneath.</p>
<p>Let’s now refactor our messy (and smelly) modal component by applying the compound components pattern.</p>
<h2 id="heading-how-to-build-a-modal-component-using-the-compound-components-pattern">How to Build a Modal Component Using the Compound Components Pattern</h2>
<p>Create a folder called <code>with-pattern</code> under the <code>src/</code> folder. We will arrange and maintain the modal component, and in the future, an accordion component under this new folder.</p>
<p>Next, create a folder called <code>modal</code> under the <code>src/with-pattern</code>. Finally, create a file called <code>Modal.jsx</code> with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// File Location: src/with-pattern/modal/Modal.jsx</span>

<span class="hljs-keyword">const</span> Modal = <span class="hljs-function">(<span class="hljs-params">{ children, isOpen, onClose }</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span>(!isOpen) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-backdrop"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-container"</span>&gt;</span>
                {children}
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-close"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onClose}</span>&gt;</span>
                    ✖
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ModalHeader</span>(<span class="hljs-params">{ children }</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-header"</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ModalBody</span>(<span class="hljs-params">{ children }</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-body"</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ModalFooter</span>(<span class="hljs-params">{ children }</span>) </span>{
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"modal-footer"</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}

Modal.Header = ModalHeader;
Modal.Body = ModalBody;
Modal.Footer = ModalFooter;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Modal;
</code></pre>
<p>Let me break it down for you:</p>
<ul>
<li><p>First, focus on the Modal component above. It doesn’t take title, body, and so on as props anymore. Rather, it accepts <code>children</code>, a special prop in React to pass any HTML elements, a group of HTMLs, JSX, or even a React component. It brings flexibility that we are no longer fixed to any particular structure to pass to the Modal component.</p>
</li>
<li><p>The JSX of the Modal component just renders the <code>children</code> prop as is, giving the entire power to the consumer of the Modal component to pass any structure it’s willing to. The Modal component uses the backdrop and container style to dictate the basic look and feel of a modal.</p>
</li>
<li><p>The Modal’s JSX also has a button to close the modal by clicking on an x. To open and close the modal, we have passed two additional props, <code>isOpen</code> and <code>onClose</code>. You can imagine <code>isOpen</code> is a state value that the consumer of this modal uses to open the modal, and the <code>onClose</code> is a function that sets the value of the <code>isOpen</code> to false to close the modal.</p>
</li>
<li><p>Then, we have defined three more components, <code>ModalHeader</code>, <code>ModalBody</code>, and <code>ModalFooter</code> which are equally flexible to accept any legit HTML structure or React component through the <code>children</code> prop. Now you can pass anything to render to the modal header. The same goes for the body and footer as well.</p>
</li>
<li><p>Next, we add the header, body, and footer as the subcomponents to the <code>Modal</code> component.</p>
<pre><code class="lang-javascript">  Modal.Header = ModalHeader;
  Modal.Body = ModalBody;
  Modal.Footer = ModalFooter;
</code></pre>
</li>
<li><p>Finally, we exported the <code>Modal</code> component.</p>
</li>
</ul>
<h3 id="heading-why-didnt-we-create-separate-files-for-the-subcomponents">Why Didn’t We Create Separate Files for the SubComponents?</h3>
<p>This question is quite natural. In general, we follow the standard practice of one component in one source file(.jsx/.tsx). Here, we seem to be breaking that rule…so are we? Actually not.</p>
<p>The golden rules are:</p>
<ul>
<li><p>The subcomponents (ModalHeader, ModalBody, and ModalFooter) are only meaningful in the context of Modal. They don’t have (or need) any existence beyond the modal.</p>
</li>
<li><p>They are small helper components that you don’t expect to reuse anywhere else.</p>
</li>
<li><p>Keeping them together is good for discoverability and is safe from potential misuse that we’ll discuss in the pitfalls section later.</p>
</li>
</ul>
<h3 id="heading-how-to-use-the-modal-component">How to Use the Modal Component</h3>
<p>So we’re sorted. Let’s now learn how to use this Modal component and see how it can bring flexibility, reusability, scalability, and testability.</p>
<p>Open the <code>App.jsx</code> file and replace the content of it with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-comment">// import Modal from "./messy/Modal";</span>
<span class="hljs-keyword">import</span> Modal <span class="hljs-keyword">from</span> <span class="hljs-string">"./with-pattern/modal/Modal"</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [isOpen, setIsOpen] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center"</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsOpen(true)}&gt;Open Modal<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">Modal</span> <span class="hljs-attr">isOpen</span>=<span class="hljs-string">{isOpen}</span> <span class="hljs-attr">onClose</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsOpen(false)}&gt;

        <span class="hljs-tag">&lt;<span class="hljs-name">Modal.Header</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Welcome!<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Modal.Header</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">Modal.Body</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
              This is a modal built with the Compound Component
              pattern.
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Modal.Body</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">Modal.Footer</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Help!<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsOpen(false)}&gt;Close<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> alert("Action Performed!")}&gt;Do Action<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Modal.Footer</span>&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">Modal</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Check out how we have passed a bunch of JSX inside &lt;Modal&gt;…&lt;/Modal&gt; as the children. It’s so powerful. We’re passing the subcomponents header, body, and footer in the sequence we want them to appear in the modal.</p>
<p>Next, if we look into the &lt;ModalHeader&gt;, &lt;ModalBody&gt;, or &lt;ModalFooter&gt; components, we can again pass anything as children to them. For example, the &lt;ModalFooter /&gt; can now take three buttons (in fact, anything else) based on the needs.</p>
<p>We can compose the components like Lego blocks to build the kind of Modal that we wish to. You don't need to have different components to represent different kinds of modals now. This single component can cater to all your modal needs without introducing any props soup drama.</p>
<p>We have a button to open the modal, and the App.jsx component manages a state called <code>isOpen</code> to tackle the opening and closing of the modal.</p>
<p>You should be able to see these changes now in the browser. Click on the open modal button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759410185904/b7adbab0-9d24-4245-92ad-84766817af12.png" alt="Open Modal Button" class="image--center mx-auto" width="1528" height="964" loading="lazy"></p>
<p>The modal dialog opens up with all the content we have passed to it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759410275413/9bff6791-3cf8-45eb-aea8-a85e9a95777d.png" alt="Modal With Pattern" class="image--center mx-auto" width="1892" height="1280" loading="lazy"></p>
<p>It’s a big leap towards achieving clean code to use the compound components design pattern. Now that you’re familiar with the basics, let’s quickly do another classic implementation of this pattern by building an Accordion component.</p>
<h2 id="heading-how-to-build-an-accordion-component-using-the-compound-components-pattern">How to Build an Accordion Component Using the Compound Components Pattern</h2>
<p>An accordion component is an array of Accordion Items. It’s a combination of a header and body that shows and hides the content when users click on the header.</p>
<p>Create a folder called <code>accordion</code> under <code>src/with-pattern</code> folder. Now, create a file called <code>Accordion.jsx</code> inside the <code>src/with-pattern/accordion</code> with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Accordion</span>(<span class="hljs-params">{ children }</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"accordion"</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AccordionItem</span>(<span class="hljs-params">{ title, children }</span>) </span>{
  <span class="hljs-keyword">const</span> [isOpen, setIsOpen] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"accordion-item"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"accordion-title"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsOpen(!isOpen)}&gt;
        {title}
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      {isOpen &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"accordion-content"</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// Attach subcomponents</span>
Accordion.Item = AccordionItem;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Accordion;
</code></pre>
<p>Here,</p>
<ul>
<li><p>We have followed the same pattern as we did for the modal previously. We have an <code>Accordion</code> component that takes a special prop called <code>children</code>, enabling the Accordion to accept any HTML/JSX/React component and render it.</p>
</li>
<li><p>Then we defined the <code>AccordionItem</code>. It takes two props: the title to create the header, and the special prop called children to form the accordion content flexibly.</p>
</li>
<li><p>The header is formed using the button that is driven by a state called <code>isOpen</code> to show/hide the content area.</p>
</li>
<li><p>The content area of an <code>AccordionItem</code> could be anything: a paragraph, a table, an image, or even a JSX combining them.</p>
</li>
<li><p>Finally, we have added the AccordionItem as the subcomponent to the Accordion component.</p>
</li>
</ul>
<p>To make the accordion look better, let’s add a few styles. Open the <code>App.css</code> file and add these styles at the end of the file:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.accordion-item</span> {
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">0.5rem</span>;
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#ddd</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;
}
<span class="hljs-selector-class">.accordion-title</span> {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">text-align</span>: left;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5rem</span>;
    <span class="hljs-attribute">font-weight</span>: bold;
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#f9f9f9</span>;
    <span class="hljs-attribute">border</span>: none;
}
<span class="hljs-selector-class">.accordion-content</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5rem</span>;
    <span class="hljs-attribute">background</span>: <span class="hljs-number">#fff</span>;
}
</code></pre>
<p>Great, let’s now use the Accordion component. Create a new file called <code>AccordionDemo.jsx</code> under the folder <code>src/with-pattern/accordion</code> with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Accordion <span class="hljs-keyword">from</span> <span class="hljs-string">"./Accordion"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AccordionDemo</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Accordion</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Accordion.Item</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"What is Compound Component Pattern?"</span>&gt;</span>
        It’s a React pattern that allows parent and child components to work
        together seamlessly while giving developers flexible composition.
      <span class="hljs-tag">&lt;/<span class="hljs-name">Accordion.Item</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">Accordion.Item</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Why use it?"</span>&gt;</span>
        It makes UI libraries like modals, tabs, accordions, menus, etc. easier
        to build and use.
      <span class="hljs-tag">&lt;/<span class="hljs-name">Accordion.Item</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">Accordion.Item</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Pitfalls?"</span>&gt;</span>
        Overusing it can lead to deeply nested structures or make things harder
        to debug if not documented well.
      <span class="hljs-tag">&lt;/<span class="hljs-name">Accordion.Item</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Accordion</span>&gt;</span></span>
  );
}
</code></pre>
<p>Check out how the <code>Accordion</code> component can accept a bunch of AccordionItem components. You can also create an array of <code>AccordionItem</code> components and pass them dynamically to the Accordion component.</p>
<p>Each of the AccordionItem components accepts the title prop value, and we passed the text as the children. If needed, you can pass any other valid JSX as a child. That’s amazing!</p>
<h3 id="heading-add-the-accordion-to-the-modal">Add the Accordion to the Modal</h3>
<p>Now, let’s take the usage of this pattern to the next level. How about using the <code>AccordionDemo</code> inside the <code>Modal</code> component? Can we do it without changing the Modal component?</p>
<p>Oh yes! Remember, the Modal component accepts any JSX as children, and so does the ModalBody component. So we can just import the AccordionDemo component into the App.jsx file and use it inside the &lt;Modal.Body&gt;…&lt;/Modal.Body&gt; as shown below, right?</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-comment">// import Modal from "./messy/Modal";</span>
<span class="hljs-keyword">import</span> Modal <span class="hljs-keyword">from</span> <span class="hljs-string">"./with-pattern/modal/Modal"</span>;

<span class="hljs-keyword">import</span> AccordionDemo <span class="hljs-keyword">from</span> <span class="hljs-string">"./with-pattern/accordion/AccordionDemo"</span>;

<span class="hljs-keyword">import</span> <span class="hljs-string">"./App.css"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [isOpen, setIsOpen] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center"</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsOpen(true)}&gt;Open Modal<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">Modal</span> <span class="hljs-attr">isOpen</span>=<span class="hljs-string">{isOpen}</span> <span class="hljs-attr">onClose</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsOpen(false)}&gt;

        <span class="hljs-tag">&lt;<span class="hljs-name">Modal.Header</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Welcome!<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Modal.Header</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">Modal.Body</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
              This is a modal built with the Compound Component
              pattern.
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">AccordionDemo</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Modal.Body</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">Modal.Footer</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Help!<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setIsOpen(false)}&gt;Close<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> alert("Action Performed!")}&gt;Do Action<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Modal.Footer</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Modal</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Now, if you run the app with these code changes, you should see the accordion appearing inside the modal. You will also be able to show/hide the accordion content and open/close the modal. This means their individual states are intact as expected.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759410454778/69fdcb6a-77a0-42e1-b060-fa2666543c94.png" alt="Accordion" class="image--center mx-auto" width="1902" height="1280" loading="lazy"></p>
<h2 id="heading-the-use-cases">The Use Cases</h2>
<p>So far, we have seen a couple of important usages of the Compound Components pattern with modal and accordion. Similarly, you can use this pattern to build reusable components like:</p>
<ul>
<li><p>Tables (Table.Head, Table.Body, Table.Row).</p>
</li>
<li><p>Any component where layout and nesting matter.</p>
</li>
</ul>
<p>Also, if you’re ever writing your own component library or design system, this pattern is a must. If you need some inspiration, look at ShadCN, Material UI, or Radix UI. They all do this.</p>
<h2 id="heading-the-pitfalls-and-anti-patterns">The Pitfalls and Anti-Patterns</h2>
<p>As you know, with great power comes great responsibility. And with patterns comes the pitfalls and anti-patterns you’ll need to be aware of. When you’re using the compound components pattern, just make sure that you:</p>
<ul>
<li><p>Don’t attach subcomponents randomly. They should belong to the parent semantically.</p>
</li>
<li><p>Avoid re-exporting subcomponents separately. It will be a disaster if someone uses the ModalFooter without a Modal. What if the ModalFooter changes tomorrow in the context of the Modal, and the other consumers are not in need/aware of that change?</p>
</li>
<li><p>Don’t attempt to make everything in the compound components pattern. The rule of thumb is, only use it when the children's structure matters, and you want to keep it flexible.</p>
</li>
</ul>
<h2 id="heading-15-days-of-react-design-patterns">15 Days of React Design Patterns</h2>
<p>I have some great news for you! After the <em>40 days of the JavaScript</em> initiative, I have now started a brand new initiative called <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC">15 Days of React Design Patterns</a>.</p>
<p>If you enjoyed learning from this article, I am sure you will love this series, featuring the 15 most important React design patterns. Check it out and join.</p>
<p><a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRyQVT__uFZvaVfWPdfyMFHC"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1759482303884/694491a4-2fd9-4515-b595-eafc925d2a18.png" alt="15 Days of React Design Patterns" class="image--center mx-auto" width="1557" height="820" loading="lazy"></a></p>
<h2 id="heading-before-we-end"><strong>Before We End...</strong></h2>
<p>That’s all! I hope you found this article insightful.</p>
<p>Let’s connect:</p>
<ul>
<li><p>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</p>
</li>
<li><p>Subscribe to my fortnightly newsletter, <a target="_blank" href="https://tapascript.substack.com/subscribe?utm_medium=fcc">The Commit Log</a>.</p>
</li>
<li><p>Follow on <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Join my <a target="_blank" href="https://discord.gg/zHHXx4vc2H">Discord Server</a>, and let’s learn together.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The JavaScript Error Handling Handbook ]]>
                </title>
                <description>
                    <![CDATA[ Errors and exceptions are inevitable in application development. As programmers, it is our responsibility to handle these errors gracefully so that the user experience of the application is not compromised. Handling errors correctly also helps progra... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-javascript-error-handling-handbook/</link>
                <guid isPermaLink="false">68715d56bc2af40281bdf584</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ error handling ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Fri, 11 Jul 2025 18:52:06 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752254732491/dd413499-64f4-4a20-8fd6-7f73cfcd55c0.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Errors and exceptions are inevitable in application development. As programmers, it is our responsibility to handle these errors gracefully so that the user experience of the application is not compromised. Handling errors correctly also helps programmers debug and understand what caused them so they can deal with them.</p>
<p>JavaScript has been a popular programming language for over three decades. We build web, mobile, PWA, and server-side applications using JavaScript and various popular JavaScript-based libraries (like ReactJS) and frameworks (like Next.js, Remix, and so on).</p>
<p>Being a loosely typed language, JavaScript imposes the challenge of handling type safety correctly. TypeScript is useful for managing types, but we still need to handle runtime errors efficiently in our code.</p>
<p>Errors like <code>TypeError</code>, <code>RangeError</code>, <code>ReferenceError</code> are probably pretty familiar to you if you’ve been building with JavaScript for a while. All these errors may cause invalid data, bad page transitions, unwanted results, or even the entire application to crash – none of which will make end users happy!</p>
<p>In this handbook, you’ll learn everything you need to know about error handling in JavaScript. We will start with an understanding of errors, their types, and occurrences. Then you’ll learn how to deal with these errors so that they don’t cause a bad user experience. At the end, you’ll also learn to build your own custom error types and clean-up methodologies to handle your code flow better for optimizations and performance.</p>
<p>I hope you enjoy reading along and practising the tasks I have provided at the end of the article.</p>
<p>This handbook is also available as a video session as part of the <a target="_blank" href="https://www.youtube.com/watch?v=t8QXF85YovE&amp;list=PLIJrr73KDmRw2Fwwjt6cPC_tk5vcSICCu">40 Days of JavaScript</a> initiative. Please check it out.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/XpMW-gxNYD8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-errors-in-javascript">Errors in JavaScript</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-handling-errors-with-the-try-and-catch">Handling Errors With the try and catch</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-the-try-block">The try Block</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-catch-block">The catch Block</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-error-handling-real-world-use-cases">Error Handling: Real-World Use Cases</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-handling-division-by-zero">Handling Division by Zero</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-handling-json">Handling JSON</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-anatomy-of-the-error-object">Anatomy of the Error Object</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-the-error-object">What is the Error Object?</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-throwing-errors-and-re-throwing-errors">Throwing Errors and Re-throwing Errors</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-rethrowing">Rethrowing</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-the-finally-with-try-catch">The finally with try-catch</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-caution-with-finally">Caution with finally</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-custom-errors">Custom Errors</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-a-real-world-use-case-of-custom-errors">A Real-World Use Case of Custom Errors</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-task-assignments-for-you">Task Assignments for You</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-find-the-output">Find the Output</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-payment-process-validation">Payment Process Validation</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-40-days-of-javascript-challenge-initiative">40 Days of JavaScript Challenge Initiative</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-before-we-end">Before We End...</a></p>
</li>
</ol>
<h2 id="heading-errors-in-javascript">Errors in JavaScript</h2>
<p>Errors and exceptions are the events that disrupt program execution. JavaScript parses and executes code line by line. The source code gets evaluated with the grammar of the programming language to ensure it is valid and executable. If there is a mismatch, JavaScript encounters a <code>parsing error</code>. You’ll need to make sure you follow the right syntax and grammar of the language to stay away from parsing errors.</p>
<p>Take a look at the code snippet below. Here, we have made the mistake of not closing the parentheses for the console.log.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">"hi"</span>
</code></pre>
<p>This will lead to a Syntax Error like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743047661114/11a445de-132f-49d0-9f3c-8516a0d21950.png" alt="Uncaught SyntaxError" class="image--center mx-auto" width="656" height="44" loading="lazy"></p>
<p>Other types of errors can happen due to wrong data input, trying to read a value or property that doesn’t exist, or acting on inaccurate data. Let’s see some examples:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(x); <span class="hljs-comment">// Uncaught ReferenceError: x is not defined</span>

<span class="hljs-keyword">let</span> obj = <span class="hljs-literal">null</span>;
<span class="hljs-built_in">console</span>.log(obj.name); <span class="hljs-comment">// Uncaught TypeError: Cannot read properties of null</span>

<span class="hljs-keyword">let</span> arr = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(<span class="hljs-number">-1</span>) <span class="hljs-comment">// Uncaught RangeError: Invalid array length</span>

<span class="hljs-built_in">decodeURIComponent</span>(<span class="hljs-string">"%"</span>); <span class="hljs-comment">// Uncaught URIError: URI malformed</span>

<span class="hljs-built_in">eval</span>(<span class="hljs-string">"var x = ;"</span>); <span class="hljs-comment">// Uncaught EvalError</span>
</code></pre>
<p>Here is the list of possible runtime errors you may encounter, along with their descriptions:</p>
<ul>
<li><p><code>ReferenceError</code> – Occurs when trying to access a variable that is not defined.</p>
</li>
<li><p><code>TypeError</code> – Occurs when an operation is performed on a value of the wrong type.</p>
</li>
<li><p><code>RangeError</code> – Occurs when a value is outside the allowable range.</p>
</li>
<li><p><code>SyntaxError</code> – Occurs when there is a mistake in the syntax of the JavaScript code.</p>
</li>
<li><p><code>URIError</code> – Occurs when an incorrect URI function is used in encoding and decoding URIs.</p>
</li>
<li><p><code>EvalError</code> – Occurs when there is an issue with the eval() function.</p>
</li>
<li><p><code>InternalError</code> – Occurs when the JavaScript engine runs into an internal limit (stack overflow).</p>
</li>
<li><p><code>AggregateError</code> – Introduced in ES2021, used for handling multiple errors at once.</p>
</li>
<li><p><code>Custom Errors</code> – These are user-defined errors, and we will learn how to create and use them soon.</p>
</li>
</ul>
<p>Have you noticed that all the code examples we used above result in a message explaining what the error is about? If you look at those messages closely, you will find a word called <code>Uncaught</code>. It means the error occurred, but it was not caught and managed. That’s exactly what we will now go for – so you know how to handle these errors.</p>
<h2 id="heading-handling-errors-with-the-try-and-catch">Handling Errors With the <code>try</code> and <code>catch</code></h2>
<p>JavaScript applications can break for various reasons, like invalid syntax, invalid data, missing API responses, user mistakes, and so on. Most of these reasons may lead to an application crash, and your users will see a blank white page.</p>
<p>Rather than letting the application crash, you can gracefully handle these situations using <code>try…catch</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// logic or code</span>
} <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-comment">// handle error</span>
}
</code></pre>
<h3 id="heading-the-try-block">The <code>try</code> Block</h3>
<p>The <code>try</code> block contains the code – the business logic – which might throw an error. Developers always want their code to be error-free. But at the same time, you should be aware that the code might throw an error for several possible reasons, like:</p>
<ul>
<li><p>Parsing JSON</p>
</li>
<li><p>Running API logic</p>
</li>
<li><p>Accessing nested object properties</p>
</li>
<li><p>DOM manipulations</p>
</li>
<li><p>… and many more</p>
</li>
</ul>
<p>When the code inside the try block throws an error, the code execution of the remaining code in the try block will be suspended, and the control moves to the nearest catch block. If no error occurs, the catch block is skipped completely.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">try</span> {
  <span class="hljs-comment">// Code that might throw an error</span>
} <span class="hljs-keyword">catch</span> (error) {
  <span class="hljs-comment">// Handle the error here</span>
}
</code></pre>
<h3 id="heading-the-catch-block">The <code>catch</code> Block</h3>
<p>The catch block runs only if an error was thrown in the try block. It receives the <code>Error object</code> as a parameter to give us more information about the error. In the example shown below, we are using something called <code>abc</code> without declaring it. JavaScript will throw an error like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">try</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"execution starts here"</span>);
    abc;
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"execution ends here"</span>);
} <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"An Error has occured"</span>, err);
}
</code></pre>
<p>JavaScript executes code line by line. The execution sequence of the above code will be:</p>
<ul>
<li><p>First, the string "execution starts here" will be logged to the console.</p>
</li>
<li><p>Then the control will move to the next line and find the <code>abc</code> there. What is it? JavaScript doesn’t find any definition of it anywhere. It’s time to raise the alarm and throw an error. The control doesn’t move to the next line (the next console log), but rather moves to the catch block.</p>
</li>
<li><p>In the catch block, we handle the error by logging it to the console. We could do many other things like show a toast message, send the user an email, or switch off a toaster (why not if your customer needs it).</p>
</li>
</ul>
<p>Without try...catch, the error would crash the app.</p>
<h2 id="heading-error-handling-real-world-use-cases">Error Handling: Real-World Use Cases</h2>
<p>Let’s now see some of the real-world use cases of error handling with try…catch.</p>
<h3 id="heading-handling-division-by-zero">Handling Division by Zero</h3>
<p>Here is a function that divides a number by another number. So, we have parameters passed to the function for both numbers. We want to make sure that the division never encounters an error for dividing a number by zero (0).</p>
<p>As a proactive measure, we have written a condition that if the divisor is zero, we will throw an error saying that division by zero is not allowed. In every other case, we will proceed with the division operation. In case of an error, the catch block will handle the error and do what’s needed (in this case, logging the error to the console).</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">divideNumbers</span>(<span class="hljs-params">a, b</span>) </span>{
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">if</span> (b === <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">const</span> err = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Division by zero is not allowed."</span>);
            <span class="hljs-keyword">throw</span> err;
        }
        <span class="hljs-keyword">const</span> result = a/b;
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The result is <span class="hljs-subst">${result}</span>`</span>);
    } <span class="hljs-keyword">catch</span>(error) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Got a Math Error:"</span>, error.message)
    }
}
</code></pre>
<p>Now, if we invoke the function with the following arguments, we will get a result of 5, and the second argument is a non-zero value.</p>
<pre><code class="lang-javascript">divideNumbers(<span class="hljs-number">15</span>, <span class="hljs-number">3</span>); <span class="hljs-comment">// The result is 5</span>
</code></pre>
<p>But if we pass the 0 value for the second argument, the program will throw an error, and it will be logged into the console.</p>
<pre><code class="lang-javascript">divideNumbers(<span class="hljs-number">15</span>, <span class="hljs-number">0</span>);
</code></pre>
<p>Output:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752115297863/02d9e89d-e5c1-4759-a11e-ab57d04bcfff.png" alt="Math Error" class="image--center mx-auto" width="927" height="130" loading="lazy"></p>
<h3 id="heading-handling-json">Handling JSON</h3>
<p>Often, you will get JSON as a response to an API call. You need to parse this JSON in your JavaScript code to extract the values. What if the API sends you some malformed JSON by mistake? You can’t afford to let your user interface crash because of this. You need to handle it gracefully – and here comes the try…catch block again to the rescue:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseJSONSafely</span>(<span class="hljs-params">str</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">JSON</span>.parse(str);
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Invalid JSON:"</span>, err.message);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }
}

<span class="hljs-keyword">const</span> userData = parseJSONSafely(<span class="hljs-string">'{"name": "tapaScript"}'</span>); <span class="hljs-comment">// Parsed</span>
<span class="hljs-keyword">const</span> badData = parseJSONSafely(<span class="hljs-string">'name: tapaScript'</span>);         <span class="hljs-comment">// Handled gracefully</span>
</code></pre>
<p>Without try...catch, the second call will crash the app.</p>
<h2 id="heading-anatomy-of-the-error-object">Anatomy of the Error Object</h2>
<p>Getting errors in programming can be a scary feeling. But <code>Error</code>s in JavaScript aren’t just some scary, annoying messages – they are structured objects that carry a lot of helpful information about what went wrong, where, and why.</p>
<p>As developers, we need to understand the anatomy of the <code>Error</code> object to help us better with faster debugging and smarter recovery in production-level application issues.</p>
<p>Let’s deep dive into the Error object, its properties, and how to use it effectively with examples.</p>
<h3 id="heading-what-is-the-error-object">What is the Error Object?</h3>
<p>The JavaScript engine throws an <code>Error</code> object when something goes wrong during runtime. This object contains helpful information like:</p>
<ul>
<li><p>An error message: This is a human-readable error message.</p>
</li>
<li><p>The error type: TypeError, ReferenceError, SyntaxError, and so on that we discussed above.</p>
</li>
<li><p>The stack trace: This helps you navigate to the root of the error. It is a string containing the stack trace at the point the error was thrown.</p>
</li>
</ul>
<p>Let’s take a look at the code snippet below. The JavaScript engine will throw an error in this code, as the variable <code>y</code> is not defined. The error object contains the error name (type), message, and the stack trace information.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">doSomething</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> x = y + <span class="hljs-number">1</span>; <span class="hljs-comment">// y is not defined</span>
}
<span class="hljs-keyword">try</span> {
  doSomething();
} <span class="hljs-keyword">catch</span> (err) {
  <span class="hljs-built_in">console</span>.log(err.name);    <span class="hljs-comment">// ReferenceError</span>
  <span class="hljs-built_in">console</span>.log(err.message); <span class="hljs-comment">// y is not defined</span>
  <span class="hljs-built_in">console</span>.log(err.stack); <span class="hljs-comment">// ReferenceError: y is not defined</span>
                          <span class="hljs-comment">// at doSomething (&lt;anonymous&gt;:2:13)</span>
                          <span class="hljs-comment">// at &lt;anonymous&gt;:5:3</span>
}
</code></pre>
<p>Tip: If you need any specific properties from the error object, you can use destructuring to do that. Here is an example where we are only interested in the error name and message, not the stack.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">try</span> {
  <span class="hljs-built_in">JSON</span>.parse(<span class="hljs-string">"{ invalid json }"</span>);
} <span class="hljs-keyword">catch</span> ({name, message}) {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Name:"</span>, name);       <span class="hljs-comment">// Name: SyntaxError</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message:"</span>, message); <span class="hljs-comment">// Message: Expected property name or '}' in JSON at position 2 (line 1 column 3)</span>
}
</code></pre>
<h2 id="heading-throwing-errors-and-re-throwing-errors">Throwing Errors and Re-throwing Errors</h2>
<p>JavaScript provides a <code>throw</code> statement to trigger an error manually. It is very helpful when you want to handle an invalid condition in your code (remember the divide by zero problem?).</p>
<p>To throw an error, you need to create an instance of the <code>Error</code> object with details and then throw it.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Something is bad!"</span>);
</code></pre>
<p>When the code execution encounters a <code>throw</code> statement,</p>
<ul>
<li><p>It stops the execution of the current code block immediately.</p>
</li>
<li><p>The control moves to the nearest catch block (if any).</p>
</li>
<li><p>If the catch block is not found, the error will not be caught. The error gets bubbled up, and may end up crashing the program. You can learn more in-depth about events and event bubbling from <a target="_blank" href="https://www.youtube.com/watch?v=ybgI5vVE668">here</a>.</p>
</li>
</ul>
<h3 id="heading-rethrowing">Rethrowing</h3>
<p>At times, catching the error itself in the catch block is not enough. Sometimes, you may not know how to handle the error completely, and you might want to do additional things, like:</p>
<ul>
<li><p>Adding more context to the error.</p>
</li>
<li><p>Logging the error into a file-based logger.</p>
</li>
<li><p>Passing the error to someone more specialized to handle it.</p>
</li>
</ul>
<p>This is where <code>rethrow</code> comes in. With rethrowing, you catch an error, do something else with it, and then throw it again.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processData</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    parseUserData();
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error in processData:"</span>, err.message);
    <span class="hljs-keyword">throw</span> err; <span class="hljs-comment">// Rethrow so the outer function can handle it too</span>
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    processData();
  } <span class="hljs-keyword">catch</span> (err) {
    handleErrorBetter(err);
  }
}
</code></pre>
<p>In the code above, the <code>processData()</code> function catches an error, logs it, and then <code>throw</code>s it again. The outer <code>main()</code> function can now catch it and do something more to handle it better.</p>
<p>In the real-world application development, you would want to separate the concerns for errors, like:</p>
<ul>
<li><p><strong>API Layer</strong> – In this layer, you can detect HTTP failures</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUser</span>(<span class="hljs-params">id</span>) </span>{
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/users/<span class="hljs-subst">${id}</span>`</span>);
    <span class="hljs-keyword">if</span> (!res.ok) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"User not found"</span>); <span class="hljs-comment">// throw it here</span>
    <span class="hljs-keyword">return</span> res.json();
  }
</code></pre>
</li>
<li><p><strong>Service Layer</strong> – In this layer, you handle business logic. So the error will be handled for invalid conditions.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUser</span>(<span class="hljs-params">id</span>) </span>{
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> fetchUser(id);
      <span class="hljs-keyword">return</span> user;
    } <span class="hljs-keyword">catch</span> (err) {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Fetching user failed:"</span>, err.message);
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Unable to load user profile"</span>); <span class="hljs-comment">// rethrowing </span>
    }
  }
</code></pre>
</li>
<li><p><strong>UI Layer</strong> – Show a user-friendly error message.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">showUserProfile</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> getUser(<span class="hljs-number">123</span>);
      renderUser(user);
    } <span class="hljs-keyword">catch</span> (err) {
      displayError(err.message); <span class="hljs-comment">// A proper message show to the user</span>
    }
  }
</code></pre>
</li>
</ul>
<h2 id="heading-the-finally-with-try-catch">The <code>finally</code> with try-catch</h2>
<p>The try…catch block gives us a way to handle errors gracefully. But you may always want to execute some code irrespective of whether an error occurred or not. For example, closing the database connection, stopping a loader, resetting some states, and so on. That’s where <code>finally</code> comes in.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">try</span> {
  <span class="hljs-comment">// Code might throw an error</span>
} <span class="hljs-keyword">catch</span> (error) {
  <span class="hljs-comment">// Handle the error</span>
} <span class="hljs-keyword">finally</span> {
  <span class="hljs-comment">// Always runs, whether an error occured or not</span>
}
</code></pre>
<p>Let’s take an example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">performTask</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Doing something cool..."</span>);
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Oops!"</span>);
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Caught error:"</span>, err.message);
  } <span class="hljs-keyword">finally</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Cleanup: Task finished (success or fail)."</span>);
  }
}

performTask();
</code></pre>
<p>In the <code>performTask()</code> function, the error is thrown after the first console log. So, the control will move to the catch block and log the error. After that, the <code>finally</code> block will execute its console log.</p>
<p>Output:</p>
<pre><code class="lang-bash">Doing something cool...
Caught error: Oops!
Cleanup: Task finished (success or fail).
</code></pre>
<p>Let’s take a more real-world use case of making an API call and handling the loading spinner:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">loadUserData</span>(<span class="hljs-params"></span>) </span>{
  showSpinner(); <span class="hljs-comment">// Show the spinner here</span>

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/api/user'</span>);
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
    displayUser(data);
  } <span class="hljs-keyword">catch</span> (err) {
    showError(<span class="hljs-string">"Failed to load user."</span>);
  } <span class="hljs-keyword">finally</span> {
    hideSpinner(); <span class="hljs-comment">// Hide spinner for both success and fail cases.</span>
  }
}
</code></pre>
<p>Usually, we show a loading spinner while making an API (asynchronous) call from the browser. Irrespective of the successful response or an error from the API call, we must stop showing the loading spinner. Instead of executing the code logic twice to stop the spinner (once inside the <code>try</code> block and then again inside the <code>catch</code> block), you can do it inside the <code>finally</code> block.</p>
<h3 id="heading-caution-with-finally">Caution with <code>finally</code></h3>
<p>The <code>finally</code> block can override return values or a thrown error. This behaviour may be confusing and can lead to bugs as well.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">test</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">'from try'</span>;
  } <span class="hljs-keyword">finally</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">'from finally'</span>;
  }
}

<span class="hljs-built_in">console</span>.log(test());
</code></pre>
<p>What do you think the above code returns?</p>
<p>It will return <code>'from finally'</code>. The return <code>'from try'</code> is completely ignored. The return from finally overrides it silently.</p>
<p>Let’s see one more example of the same problem:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">willThrow</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Original Error"</span>);
  } <span class="hljs-keyword">finally</span> {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Overriding Error"</span>); <span class="hljs-comment">// The original error is lost</span>
  }
}

<span class="hljs-keyword">try</span> {
  willThrow();
} <span class="hljs-keyword">catch</span> (err) {
  <span class="hljs-built_in">console</span>.log(err.message); <span class="hljs-comment">// "Overriding Error"</span>
}
</code></pre>
<p>Here, the original error (<code>"Original Error”</code>) is swallowed. The finally block overrides the actual root cause.</p>
<p>When using <code>finally</code>:</p>
<ul>
<li><p>Avoid returns and throws from <code>finally</code> as much as possible.</p>
</li>
<li><p>Avoid performing logic in the <code>finally</code> block that may impact the actual outcome. The <code>try</code> block is the best place for that.</p>
</li>
<li><p>Any critical decision-making must be avoided inside the <code>finally</code> block</p>
</li>
<li><p>Use <code>finally</code> for cleanup activities, such as closing files, connections, and stopping loading spinners, etc.</p>
</li>
<li><p>Ensure the <code>finally</code> block contains side-effect-free code.</p>
</li>
</ul>
<h2 id="heading-custom-errors">Custom Errors</h2>
<p>Using the generic Error and its existing types, like ReferenceError, SyntaxError, and so on, can be a bit vague in complex applications. JavaScript lets you create custom errors that are more related to your business use cases. The custom errors can provide:</p>
<ul>
<li><p>Additional contextual information about the error.</p>
</li>
<li><p>Clarity about the error</p>
</li>
<li><p>More readable logs</p>
</li>
<li><p>The ability to handle multiple error cases conditionally.</p>
</li>
</ul>
<p>A custom error in JavaScript is a user-defined error type that extends the built-in Error class. The custom error should be an <a target="_blank" href="https://www.youtube.com/watch?v=kG5t34ciG9w">ES6 Class</a> that extends JavaScript’s Error class. We can use the <code>super()</code> in the constructor function to inherit the message property of the Error class. You can optionally assign a name and clean the stack trace for the custom error.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyCustomError</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Error</span> </span>{
  <span class="hljs-keyword">constructor</span>(message) {
    <span class="hljs-built_in">super</span>(message);         <span class="hljs-comment">// Inherit message property</span>
    <span class="hljs-built_in">this</span>.name = <span class="hljs-built_in">this</span>.constructor.name; <span class="hljs-comment">// Optional but recommended</span>
    <span class="hljs-built_in">Error</span>.captureStackTrace(<span class="hljs-built_in">this</span>, <span class="hljs-built_in">this</span>.constructor); <span class="hljs-comment">// Clean stack trace</span>
  }
}
</code></pre>
<p>Let’s now see a real-world use case for a custom error.</p>
<h3 id="heading-a-real-world-use-case-of-custom-errors">A Real-World Use Case of Custom Errors</h3>
<p>Using a form on a web page is an extremely common use case. A form may contain one or more input fields. It is recommended to validate the user inputs before we process the form data for any server actions.</p>
<p>Let’s create a custom validation error we can leverage for validating multiple form input data, like the user’s email, age, phone number, and more.</p>
<p>First, we’ll create a class called <code>ValidationError</code> that extends the <code>Error</code> class. The constructor function sets up the <code>ValidationError</code> class with an error message. We can also instantiate additional properties, like name, field, and so on.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ValidationError</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Error</span> </span>{
  <span class="hljs-keyword">constructor</span>(field, message) {
    <span class="hljs-built_in">super</span>(<span class="hljs-string">`<span class="hljs-subst">${field}</span>: <span class="hljs-subst">${message}</span>`</span>);
    <span class="hljs-built_in">this</span>.name = <span class="hljs-string">"ValidationError"</span>;
    <span class="hljs-built_in">this</span>.field = field;
  }
}
</code></pre>
<p>Now, let's see how to use <code>ValidationError</code>. We can validate a user model to check its properties and throw a <code>ValidationError</code> whenever the expectations mismatch.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">validateUser</span>(<span class="hljs-params">user</span>) </span>{
  <span class="hljs-keyword">if</span> (!user.email.includes(<span class="hljs-string">"@"</span>)) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ValidationError(<span class="hljs-string">"email"</span>, <span class="hljs-string">"Invalid email format"</span>);
  }
  <span class="hljs-keyword">if</span> (!user.age || user.age &lt; <span class="hljs-number">18</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ValidationError(<span class="hljs-string">"age"</span>, <span class="hljs-string">"User must be 18+"</span>);
  }
}
</code></pre>
<p>In the code snippet above,</p>
<ul>
<li><p>We throw an invalid email format validation error if the user’s email doesn’t include the <code>@</code> symbol.</p>
</li>
<li><p>We throw another validation error if the age information of the user is missing or is below 18.</p>
</li>
</ul>
<p>A custom error gives us the power to create domain/usage-specific error types to keep the code more manageable and less error-prone.</p>
<h2 id="heading-task-assignments-for-you">Task Assignments for You</h2>
<p>If you have read the handbook this far, I hope you now have a solid understanding of JavaScript Error Handling. Let’s try out some assignments based on what we have learned so far. It’s going to be fun.</p>
<h3 id="heading-find-the-output">Find the Output</h3>
<p>What will be the output of the following code snippet and why?</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">let</span> r = p + <span class="hljs-number">50</span>;
    <span class="hljs-built_in">console</span>.log(r);
} <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"An error occurred:"</span>, error.name);
}
</code></pre>
<p>Options are:</p>
<ul>
<li><p>ReferenceError</p>
</li>
<li><p>SyntaxError</p>
</li>
<li><p>TypeError</p>
</li>
<li><p>No error, it prints 10</p>
</li>
</ul>
<h3 id="heading-payment-process-validation">Payment Process Validation</h3>
<p>Write a function <code>processPayment(amount)</code> that verifies if the amount is positive and does not exceed the balance. If any condition fails, throw appropriate errors.</p>
<p>Hint: You can think of creating a Custom Error here.</p>
<h2 id="heading-40-days-of-javascript-challenge-initiative">40 Days of JavaScript Challenge Initiative</h2>
<p>There are 101 ways of learning something. But nothing can beat structured and progressive learning methodologies. After spending more than two decades in Software Engineering, I’ve been able to gather the best of JavaScript together to create the <a target="_blank" href="https://www.youtube.com/playlist?list=PLIJrr73KDmRw2Fwwjt6cPC_tk5vcSICCu">40 Days of JavaScript</a> challenge initiative.</p>
<p>Check it out if you want to learn JavaScript with fundamental concepts, projects, and assignments for free (forever). Focusing on the fundamentals of JavaScript will prepare you well for a future in web development.</p>
<h2 id="heading-before-we-end"><strong>Before We End...</strong></h2>
<p>That’s all! I hope you found this article insightful.</p>
<p>Let’s connect:</p>
<ul>
<li><p>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</p>
</li>
<li><p>Follow on <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Check out and follow my open-source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ If-Else vs Switch Case in JavaScript – Which One is Better? ]]>
                </title>
                <description>
                    <![CDATA[ JavaScript has been a popular programming language for almost 30 years now. Whether you’re using it for web applications, mobile applications, backend services, or even desktop applications, you’ll find that JavaScript has deep roots. Many of the lib... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/if-else-vs-switch-case-in-javascript/</link>
                <guid isPermaLink="false">67bf38654fdd15eb4db76755</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Wed, 26 Feb 2025 15:51:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1740585035432/f829418f-0efc-4af9-b1c7-7233b6640abc.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>JavaScript has been a popular programming language for almost 30 years now. Whether you’re using it for web applications, mobile applications, backend services, or even desktop applications, you’ll find that JavaScript has deep roots.</p>
<p>Many of the libraries and frameworks you likely use to build modern web applications are based on JavaScript, like React.js, Next.js, Angular, Solid.js, Vue.js, and Node.js to name a few.</p>
<p>While these libraries and frameworks provide a lot of helpful abstractions on low-level programming, as an application developer you still have to have a solid grasp of JavaScript fundamentals to be able to use them effectively.</p>
<p>A very basic programming concept is <code>Control Flow</code> and decision-making. And it’s not related to JavaScript alone – you’ll encounter it in most of the programming languages you work with.</p>
<p>In this article, you’ll learn about two primary techniques for managing control flow in JavaScript: using <code>if-else</code> and <code>switch-case</code>. Many of you may be aware of their constructs and usages. But the focus of this article is to draw a comparison between the two, so that by the end of it you’ll know which one to choose for each use case.</p>
<p>This article is also available as a video tutorial as part of the <a target="_blank" href="https://www.youtube.com/watch?v=t8QXF85YovE&amp;list=PLIJrr73KDmRw2Fwwjt6cPC_tk5vcSICCu">40 Days of JavaScript</a> initiative. Please check it out.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Fn_DhBu3VyU" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-control-flow-in-javascript">What is Control Flow in JavaScript?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-handle-control-flow-with-the-if-else-block">How to Handle Control Flow With the if-else Block</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-handle-control-flow-with-the-switch-case-statement">How to Handle Control Flow With the switch Statement</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-comparison-if-else-vs-switch-case">The Comparison: if-else vs switch-case</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-before-we-end">Before We End...</a></p>
</li>
</ul>
<h2 id="heading-what-is-control-flow-in-javascript">What is Control Flow in JavaScript?</h2>
<p>In JavaScript, your code runs line-by-line starting from the first line up to the last line of the JavaScript file. This order of code execution by the JavaScript interpreter is called <code>control flow</code>.</p>
<p>At times, your program may require changes in the flow of execution depending on one or more conditions. These conditions will determine whether a set of statements in the JavaScript file should be executed or not.</p>
<p>Let’s look at this example of a JavaScript file (some.js) shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740121611950/4bcaf223-1d72-4a5d-b9c6-b176e72dd93a.png" alt="Control FLOW" class="image--center mx-auto" width="1183" height="747" loading="lazy"></p>
<p>The file has 12 lines of code. Once this file is loaded into the JavaScript environment, the interpreter will start the execution from line number 1 and will proceed line by line. At line number 4, the interpreter will encounter a <code>control statement</code> which will allow the interpreter to either execute or skip line number 5. In our case, it is skipping the execution of line number 5.</p>
<p>So, the control goes to line 6, executes every line, and proceeds to line 9. Then, it encounters another control statement to skip line 10, start execution from line 11, and finish at the last line, line 12.</p>
<p>There are two major control statements in JavaScript that you must be aware of:</p>
<ul>
<li><p><code>if</code> and <code>if-else</code></p>
</li>
<li><p><code>switch-case</code></p>
</li>
</ul>
<p>First, let’s discuss them with examples to understand how they impact the control flow of code execution.</p>
<h2 id="heading-how-to-handle-control-flow-with-the-if-else-block">How to Handle Control Flow With the <code>if-else</code> Block</h2>
<p>The <code>if</code> keyword and the combination of the <code>if-else</code> keywords help us create control statements in the code execution flow. With <code>if</code>, a block of code will be executed only when a test condition is passed. A passed condition returns a <code>true</code>, and a failed condition returns a <code>false</code>.</p>
<p>Let’s take an example: If you catch the bus, you will get home on time. Now, if you had to write this scenario programmatically, you’d create a condition for <code>cacthingBus</code>. Then, you’d pass the condition to the <code>if</code> using a pair of parenthesis. The code block associated with the <code>if</code> gets executed if the condition results in true.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> catchingBus = <span class="hljs-literal">true</span>;

<span class="hljs-comment">// Some code here...</span>

<span class="hljs-keyword">if</span> (catchingBus) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"I will get home on time"</span>);
} 

<span class="hljs-comment">// Some other code here...</span>
</code></pre>
<p>In the code snippet above, the result of the condition <code>catchingBus</code> is <code>true</code>. So the code execution flow will enter the if-block and execute the console log, <code>I will get home on time</code>. If you change the value of the condition to <code>false</code>, the if-block will be skipped. In such cases, you may want to handle an alternate use case – so you bring an <code>else</code> block along with the <code>if</code>.</p>
<p>In the code snippet below, we have both if and else. In this case, the condition results in <code>false</code>. So, the <code>else</code> block will be executed and <code>I will be late to get home</code> will be logged into the console.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> catchingBus = <span class="hljs-literal">false</span>;

<span class="hljs-keyword">if</span> (catchingBus) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"I will get home on time"</span>);
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"I will be late to get home"</span>);
}
</code></pre>
<p>You may have more than a pair of if-else for handling complex problems. Let’s take an example of a grading system. If your score is 90 or above, you get a grade A, for 80 or above, a Grade B, for 70 or above, and a Grade C, or else you fail.</p>
<p>Let’s write the program for it with the help of the if-else. As we have multiple conditions to handle, we will need multiple if-blocks and associated else-blocks.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> score = <span class="hljs-number">76</span>;

<span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">90</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Grade A"</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">80</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Grade B"</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">70</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Grade C"</span>);
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Fail"</span>);
}
</code></pre>
<p>Combining multiple if-else statements is a great way to handle checking for multiple conditions and take action based on a condition that passes or fails.</p>
<h2 id="heading-how-to-handle-control-flow-with-the-switch-case-statement">How to Handle Control Flow with the <code>switch-case</code> Statement</h2>
<p>While if-else is great when we’re checking multiple possible conditions, you can use <code>switch-case</code> to handle multiple conditions based on a <code>single value</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">switch</span>(value) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"case 1"</span>: <span class="hljs-comment">// do something</span>
    <span class="hljs-keyword">case</span> <span class="hljs-string">"case 2"</span>: <span class="hljs-comment">// do something</span>
    <span class="hljs-keyword">case</span> <span class="hljs-string">"case 3"</span>: <span class="hljs-comment">// do something</span>
    <span class="hljs-keyword">case</span> <span class="hljs-string">"case 4"</span>: <span class="hljs-comment">// do something</span>
    <span class="hljs-keyword">default</span>: <span class="hljs-comment">// do something</span>
}
</code></pre>
<p>Unlike <code>if-block</code>, the <code>switch-block</code> accepts a value and then checks for a matching case for that value. When a case is matched, JavaScript will execute the code block for the case. Using a <code>break</code> statement will exit from the switch block. When none of the cases match, the <code>default</code> will be executed.</p>
<p>In the code snippet below, we are checking for a match based on a position value. So, the position value is passed to the switch statement. Now, if the position value is 1, the first case will be matched because it matches for the value 1. Likewise, it will be the same for the positions 2, 3, or 4. If we pass a position value that is not 1,2, 3, or 4, the default block will be executed.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> position = <span class="hljs-number">10</span>;

<span class="hljs-keyword">switch</span> (position) {
    <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Print 1"</span>);
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Print 2"</span>);
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Print 3"</span>);
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">4</span>:
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Print 4"</span>);
        <span class="hljs-keyword">break</span>;

    <span class="hljs-keyword">default</span>:
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Nothing is matched"</span>);
}
</code></pre>
<h2 id="heading-the-comparison-if-else-vs-switch-case">The Comparison: if-else vs switch-case</h2>
<p>Now, it’s time to compare each of these approaches. Apart from their syntactical differences, there are a few key differences and considerations you need to keep in mind before opting for one instead of the other:</p>
<ul>
<li><p>Use if-else when you have to handle complex logical conditions. But if you need to check for a fixed value like numbers, strings, and so on, and then match it to a specific case value, go for switch-case.</p>
</li>
<li><p>When there are many if-else blocks, the readability of the code starts going downhill. It’s much easier to read case labels for switch-case.</p>
</li>
<li><p>If there are too many if-else blocks, the performance may be slower than the switch-case block. In many JavaScript engines, switch statements are optimized. They use a jump table for the JavaScript engine to directly jump into the correct case than evaluate each condition sequentially.</p>
</li>
</ul>
<p>Let’s understand with an example. Check out the following code snippet written using the if-else blocks:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> value = <span class="hljs-number">3</span>;

<span class="hljs-keyword">if</span> (value === <span class="hljs-number">1</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"One"</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (value === <span class="hljs-number">2</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Two"</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (value === <span class="hljs-number">3</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Three"</span>);
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Not found"</span>);
}
</code></pre>
<p>In this case,</p>
<ul>
<li><p>All the if-else statements will be executed sequentially. The JavaScript engine will check for each condition one by one until a match is found.</p>
</li>
<li><p>If the matching condition is towards the bottom, then all the conditions above it must be checked. So the if-else can be slower when we have a worst-case scenario for the match. In the above example, if the match is for the value 3, the JavaScript interpreter finishes checking for values 1 and 2, before checking the value 3.</p>
</li>
</ul>
<p>Now, the same result with the switch case:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> value = <span class="hljs-number">3</span>;

<span class="hljs-keyword">switch</span> (value) {
    <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"One"</span>);
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Two"</span>);
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Three"</span>);
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">default</span>:
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Not found"</span>);
}
</code></pre>
<p>Here,</p>
<ul>
<li><p>The JavaScript engine may have the jumping table created.</p>
</li>
<li><p>The engine directly jumps into case 3, skipping all other unnecessary checks, so it’ll be faster. But keep in mind that this difference in performance is negligible for a small number of conditions.</p>
</li>
</ul>
<p>I hope these points help you to choose between the if-else and switch statements more easily.</p>
<h2 id="heading-before-we-end"><strong>Before We End...</strong></h2>
<p>That’s all. I hope you found this article insightful. Focusing on the fundamentals of JavaScript will prepare you well for a future in web development. Check out my <a target="_blank" href="https://www.youtube.com/watch?v=t8QXF85YovE&amp;list=PLIJrr73KDmRw2Fwwjt6cPC_tk5vcSICCu">40 Days of JavaScript initiative</a> if you want to learn JavaScript with fundamental concepts, projects, and assignments for free (forever).</p>
<p>Let’s Connect:</p>
<ul>
<li><p>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</p>
</li>
<li><p>Follow on <a target="_blank" href="https://twitter.com/tapasadhikary">X (Twitter</a>) or <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Check out and follow my Open Source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</p>
</li>
<li><p>I regularly publish meaningful posts on my <a target="_blank" href="https://blog.greenroots.info/">GreenRoots Blog</a>, you may find them helpful, too.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself, and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Integrate Discord Webhooks with Next.js 15 – Example Project ]]>
                </title>
                <description>
                    <![CDATA[ You’ve likely seen (or used) contact forms on websites that ask for customer feedback, potential work opportunities, customer contact info, and so on. But do you know what’s required to get all that feedback, contact info, and data sent to a private ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/integrate-discord-webhooks-with-nextjs-15-example-project/</link>
                <guid isPermaLink="false">678fa927b9b8fe257214e1be</guid>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ discord ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webhooks ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Tue, 21 Jan 2025 14:03:19 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737468174839/93832182-b4a9-48c0-aee5-cd8d716fc47a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You’ve likely seen (or used) contact forms on websites that ask for customer feedback, potential work opportunities, customer contact info, and so on. But do you know what’s required to get all that feedback, contact info, and data sent to a private Discord text channel the moment the user submits it?</p>
<p>In this case, there is no database to store the information. Rather, you just have a free Discord text channel that keeps the data as a sequence of messages in chat. And an admin/moderator/user with the required access rights can read through these messages and take the appropriate action.</p>
<p>In case you are new to Discord, it’s a great platform for chatting, playing video games, having calls, and even running a virtual team for your startup. It’s free, and you can download it from <a target="_blank" href="https://discord.com/">here</a>.</p>
<p>Alright, coming back to the topic, I had a requirement like this to implement using Discord’s webhook and Next.js. I learned a lot from the activity. So I wrote this step-by-step tutorial about that process.</p>
<p>The primary objective here is to understand:</p>
<ul>
<li><p>What is a Webhook and what are the use cases?</p>
</li>
<li><p>How to Integrate a webhook with a web application framework like Next.js</p>
</li>
<li><p>How to build a user interface with the latest APIs and components from Next.js</p>
</li>
</ul>
<p>I hope you’ll like it. If you want to learn from a video, the article is also available as a video tutorial:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/6h-y1aRzvhY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-a-webhook">What is a Webhook?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-configure-a-webhook-on-discord">How to Configure a Webhook on Discord</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-nextjs-project">How to Create a Next.js Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-environment-variables">How to Set Environment Variables</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-integrate-the-webhook-with-the-nextjs-form-component">How to Integrate the Webhook with the Next.js Form Component</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-create-the-form">Create the Form</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-create-the-server-action">Create the Server Action</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-update-the-app-page">How to Update the App Page</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-lets-test-it-out">Let’s Test it Out</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-improve-the-message-feedback-using-react-19s-useactionstate-hook">How to Improve the Message feedback using React 19’s useActionState Hook</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-set-up-a-toaster">Set up a toaster</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-enhance-the-form-with-the-useactionstate-hook">Enhance the Form with the useActionState Hook</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-update-the-server-action-to-return-results">How to Update the Server Action to Return Results</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-lets-test-it-one-more-time">Let’s Test it One More Time</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-source-code-and-resources">Source Code and Resources</a></p>
</li>
</ol>
<h2 id="heading-what-is-a-webhook">What is a Webhook?</h2>
<p>Assume we have an email service that connects to a third-party email sender to send emails to users. Traditionally, there will be an API gateway to talk to the email service from the client devices. When the request is received, the email service will contact the email-sending provider.</p>
<p>While the email-sending provider processes the emails, the email service needs to know their status. One generic way to handle this is for the email service to poll for the status at a short frequency and update the client as and when the status changes. But this method has many drawbacks, such as resource mis-utilization, unnecessary connections, and poor performance.</p>
<p>On the contrary, how about the email service registers a callback URL that the email sender can call with relevant information when the email-sending action has been completed? This way, there is no unnecessary polling. Rather, the email sender can proactively inform the email service of a success or a failure after attempting to send the email. Then, the email service can respond to the clients regarding their status accordingly.</p>
<p>This registered callback is called a <code>Webhook</code>. Webhooks are widely used today in various industries like payments and checkout, system health monitoring, and third-party app integrations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735270052821/366027ef-bd79-4825-ba51-58cdaf3d3705.png" alt="Webhook flow" class="image--center mx-auto" width="1637" height="644" loading="lazy"></p>
<h2 id="heading-how-to-configure-a-webhook-on-discord">How to Configure a Webhook on Discord</h2>
<p>You should now have an idea of how webhooks work, so let’s configure one with Discord.</p>
<p>Create or select a text channel on your Discord server. Click on the <code>Edit Channel</code> button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735206358936/d94926f1-381a-451b-95f8-ddb7747dba70.png" alt="edit channel" class="image--center mx-auto" width="306" height="382" loading="lazy"></p>
<p>Then, from the left-side navigation menu, select the <code>Integration</code> option. You should see the <code>Webhooks</code> option listed there.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735206416398/eedf690f-1f75-48f2-8da7-ef1e9c9558da.png" alt="Integration of Webhooks" class="image--center mx-auto" width="1194" height="472" loading="lazy"></p>
<p>Click on the <code>Webhooks</code> option and then click on the <code>New Webhook</code> button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735206460104/540097f7-8e1e-41db-b2d6-d2ef1f14055b.png" alt="New Webhook" class="image--center mx-auto" width="896" height="408" loading="lazy"></p>
<p>Give your webhook a name, and you can optionally upload a photo. This can be helpful when you have multiple webhooks and you want to quickly identify them by their photo and name.</p>
<p>Now, click on the <code>Copy Webhook URL</code> button to copy the webhook URL. Keep it safe somewhere, as we will be using it shortly in our application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735206520757/0718e9e0-b16b-4156-a1bd-40ce28ed2ff4.png" alt="Edit the Webhook" class="image--center mx-auto" width="770" height="380" loading="lazy"></p>
<p>That’s it. Now let’s create a Next.js 15 application so we can integrate the webhook with it.</p>
<h2 id="heading-how-to-create-a-nextjs-project">How to Create a Next.js Project</h2>
<p>Open the terminal and use the following command to create a Next.js application:</p>
<pre><code class="lang-bash">npx create-next-app@latest
</code></pre>
<p>You’ll have to provide a few inputs for the initial project to create it. I will be using JavaScript (as opposed to TypeScript), Tailwind CSS, App Router, and Turbopack for this project. So I’ve opted for those choices by providing <code>Yes</code> as the response.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736133367746/03ebe408-3d6f-44ac-9629-5d08a4f30eab.png" alt="Nexy.js project creation" class="image--center mx-auto" width="3015" height="1763" loading="lazy"></p>
<p>With that, you’ve created a Next.js project you can use for the rest of the tutorial.</p>
<h2 id="heading-how-to-set-environment-variables">How to Set Environment Variables</h2>
<p>Create a <code>.env</code> file at the root of your project. We will now create an environment variable secret with the webhook URL you had copied before. Create an entry in the .env file like this:</p>
<pre><code class="lang-bash">DISCORD_WEBHOOK_URL=&lt;YOUR_DISCORD_WEBHOOK_URL&gt;
</code></pre>
<p>Make sure you replace the <code>&lt;YOUR_DISCORD_WEBHOOK_URL&gt;</code> with your actual webhook URL in the <code>.env</code> file. Remember, you must not commit and push this file to your version control. So, make sure that the <code>.env</code> file has been added to the <code>.gitignore</code> file of the project.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736912358788/d98af5b1-ab61-46c3-92d5-a8772d34e4f2.png" alt=".gitignore" class="image--center mx-auto" width="1282" height="708" loading="lazy"></p>
<h2 id="heading-how-to-integrate-the-webhook-with-the-nextjs-form-component">How to Integrate the Webhook with the Next.js <code>Form</code> component</h2>
<p>Now, we will create the user interface to capture inputs from the user and send those to the Discord text channel using the webhook.</p>
<p>Let’s create a simple message form using the <code>&lt;Form /&gt;</code> component from Next.js. The <code>&lt;Form/&gt;</code> component is an extension of HTML’s native form with more flexibilities and features introduced by the release of Next.js 15. I would suggest that you <a target="_blank" href="https://www.youtube.com/watch?v=vl_aGFMShg0">go over this project-based video</a> tutorial if you are interested in learning more about this new addition to Next.js.</p>
<p>Our strategy here is very straightforward:</p>
<ul>
<li><p>We will create a form and add an action to it using the form’s <code>action</code> prop.</p>
</li>
<li><p>We will then create a <a target="_blank" href="https://www.youtube.com/watch?v=gQ2bVQPFS4U">Server Action</a> using the webhook URL to communicate with Discord.</p>
</li>
<li><p>The action will be invoked when the user fills up the form and submits it. Thus the webhook communication will be done.</p>
</li>
</ul>
<p>Let’s write the code for these functionalities now.</p>
<h3 id="heading-create-the-form">Create the Form</h3>
<p>Create a folder called <code>_components</code> under the <code>app/</code> directory. Now, create a file <code>message-form.jsx</code> under the <code>app/_components/</code> folder with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Form <span class="hljs-keyword">from</span> <span class="hljs-string">"next/form"</span>;
<span class="hljs-keyword">import</span> { sendDiscordMessage } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>;

<span class="hljs-keyword">const</span> MessageForm = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{sendDiscordMessage}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your name"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-1 rounded w-[300px] my-2"</span>
        <span class="hljs-attr">required</span>
      /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your e-mail"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-1 rounded w-[300px] my-2"</span>
        <span class="hljs-attr">required</span>
      /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your Image Url"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"dp"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-1 rounded w-[300px] my-2"</span>
      /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">select</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"type"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"p-1 rounded border my-2 w-[300px]"</span>
        <span class="hljs-attr">required</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span>Message Type<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"thanks"</span>&gt;</span>Say, Thanks!<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"qa"</span>&gt;</span>QA<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"general"</span>&gt;</span>General<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"What do you want to say?"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-1 rounded w-[300px] my-2"</span>
        <span class="hljs-attr">required</span>
      /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-blue-500 w-[70px] text-white rounded-md"</span>
      &gt;</span>
        Send
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Form</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MessageForm;
</code></pre>
<p>Here, we have created a basic form with five fields for users to enter their name, email, profile image URL, message type (general, thanks, qa), and the message. There is a send button as well to submit the form.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735271967544/3313c084-1526-435b-9288-bfa93cdbcb05.png" alt="The simple form we've created" class="image--center mx-auto" width="502" height="466" loading="lazy"></p>
<p>We have used the <code>Form</code> component from the <code>next/form</code> package. The <code>Form</code> component allows us to execute a function on the server (server action) with the help of its <code>action</code> attribute. As you can see in the code above, we have imported a server action <code>sendDiscordMessage</code> and used that as the value for the <code>action</code> attribute of the form.</p>
<pre><code class="lang-xml"> <span class="hljs-tag">&lt;<span class="hljs-name">Form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{sendDiscordMessage}</span>&gt;</span>
</code></pre>
<p>Now, let’s create the server action so that we can submit the form with it.</p>
<h3 id="heading-create-the-server-action">Create the Server Action</h3>
<p>We’ll use a server action to send messages to Discord using webhooks. Create a folder called <code>actions</code> under the <code>app/</code> directory. It’s a convention to keep all the actions colocated under the <code>actions/</code> directory. Now, create a file called <code>index.js</code> under the <code>app/actions/</code> directory with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> sendDiscordMessage = <span class="hljs-keyword">async</span> (formData) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> rawFormEntries = <span class="hljs-built_in">Object</span>.fromEntries(formData);

    <span class="hljs-built_in">console</span>.log(rawFormEntries);

    <span class="hljs-keyword">await</span> fetch(process.env.DISCORD_WEBHOOK_URL, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        <span class="hljs-attr">username</span>: rawFormEntries?.username,
        <span class="hljs-attr">avatar_url</span>: rawFormEntries?.dp || <span class="hljs-string">"https://i.imgur.com/mDKlggm.png"</span>,
        <span class="hljs-attr">content</span>: rawFormEntries?.message,
        <span class="hljs-attr">embeds</span>: [
          {
            <span class="hljs-attr">fields</span>: [
              {
                <span class="hljs-attr">name</span>: <span class="hljs-string">"Email"</span>,
                <span class="hljs-attr">value</span>: rawFormEntries?.email,
                <span class="hljs-attr">inline</span>: <span class="hljs-literal">true</span>,
              },
              {
                <span class="hljs-attr">name</span>: <span class="hljs-string">"Message Type"</span>,
                <span class="hljs-attr">value</span>: rawFormEntries?.type,
                <span class="hljs-attr">inline</span>: <span class="hljs-literal">true</span>,
              },
            ],
          },
        ],
      }),
    })
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.log(err.message);
  }
};
</code></pre>
<p>Let’s understand what’s going on in the above code:</p>
<ul>
<li><p>In Next.js (or with React 19), a server function (aka server action) needs a special directive called <code>”use server”</code> at the top of the file. So we have declared that.</p>
</li>
<li><p>A server action is an async function that gets the <code>formData</code> as a parameter. The <code>formData</code> will contain the values of all the form fields submitted by the user. We can use the <code>Object.formEntries()</code> API to get a key-value pair from the <code>formData</code>. <a target="_blank" href="https://www.youtube.com/shorts/gNIO_6FcRrE">Check this out</a> to learn the best way to handle formData in JavaScript.</p>
</li>
<li><p>Next, we used the Discord webhook URL to make a <code>POST</code> call with the required payload to create the message.</p>
</li>
<li><p>Let’s understand the payload format well. We need to follow a specific payload structure for the discord webhook to create the message. It follows a schema to have the following:</p>
<ul>
<li><p><code>username</code>: the name of the message sender. It appears at the top of the message. We’re reading the name field from the submitted data and populating the <code>username</code> field.</p>
</li>
<li><p><code>avatar_url</code>: the profile photo of the message sender. We have a <code>dp</code> field in the form to capture the profile photo URL. We’re using that, and in case the user does not provide it, we’re using a default image as the profile photo.</p>
</li>
<li><p><code>content</code>: The <code>content</code> field is the actual message content. We are reading the value of the <code>message</code> field and populating the value.</p>
</li>
<li><p><code>embeds</code>: In the Discord message, you can use embeds. These embeds could be text messages, images, or videos. We will utilize the embeds to show the email and message type information. The <code>embeds</code> is an array of fields. In each of the fields, we have passed the <code>email</code> and message <code>type</code> values as the <code>inline</code> values. Inline values will appear in line, side by side.</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-how-to-update-the-app-page">How to Update the App Page</h2>
<p>Finally, let’s update the application’s page with our form component so that everything gets stitched together. Open the <code>page.js</code> file under the <code>app/</code> directory and paste in the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> MessageForm <span class="hljs-keyword">from</span> <span class="hljs-string">"./_components/message-form"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col justify-center items-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl my-3"</span>&gt;</span>Send a message to tapaScript<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">MessageForm</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      ) 
}
</code></pre>
<p>Here we have integrated the form with the app page so that we can access it on the browser.</p>
<h2 id="heading-lets-test-it-out">Let’s Test it Out</h2>
<p>Now you can run the app with the command <code>yarn dev</code> from your terminal. The app will be available on <code>localhost:3000</code> by default. Open a browser tab and hit the URL <code>http://localhost:3000</code>. You should see a form like the one below. Fill it out with values and hit the <code>Send</code> button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735272054425/12e3894b-534a-436b-8e18-e076799e5a4f.png" alt="form" class="image--center mx-auto" width="585" height="489" loading="lazy"></p>
<p>Go to the text channel of your Discord server and check for a message that should appear there momentarily. Check that the fields of the message match the input values you provided in the form.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735272074694/b795bf9f-adfd-4ff8-aed5-5fe07c49e47b.png" alt="output" class="image--center mx-auto" width="1080" height="428" loading="lazy"></p>
<p>TADA! We have done it. But hold on – we can make it even better. Did you notice that we aren’t showing any kind of feedback saying the “Message has been sent successfully”, or “There are issues in sending the message”? We’re not taking care of providing the result of the server action to the form component. Let’s fix that.</p>
<h2 id="heading-how-to-improve-the-message-feedback-using-react-19s-useactionstate-hook">How to Improve the Message Feedback using React 19’s useActionState Hook</h2>
<p><code>React 19</code> introduced a hook called <a target="_blank" href="https://www.youtube.com/watch?v=PWFKgdGmhxg">useActionState</a> that helps you update the state based on the result of a server action. Let’s use this hook to enhance the message form and the server action so that when the action gets executed successfully (or fails), we can notify the form component to change its state and show the success/error messages accordingly.</p>
<h3 id="heading-set-up-a-toaster">Set up a toaster</h3>
<p>We will use a toast message to show the success/error messages. Let’s use the toast library called <code>sonner</code>. First, install it with this command:</p>
<pre><code class="lang-bash">yarn add sonner
</code></pre>
<p>Now, we have to add the <code>Toaster</code> from <code>sonner</code> to our app. The best place to add it is at the root level Layout of the application. Open the <code>layout.js</code> file and import the <code>Toaster</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Toaster } <span class="hljs-keyword">from</span> <span class="hljs-string">'sonner'</span>;
</code></pre>
<p>Then, use the <code>Toaster</code> in the JSX of the layout:</p>
<pre><code class="lang-xml"> <span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">body</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">geistSans.variable</span>} ${<span class="hljs-attr">geistMono.variable</span>} <span class="hljs-attr">antialiased</span>`}
      &gt;</span>
        {children}
        <span class="hljs-tag">&lt;<span class="hljs-name">Toaster</span> <span class="hljs-attr">richColors</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>That’s it. The toaster set-up is done. Now we will be able to use it in our components to show the toast messages.</p>
<h3 id="heading-enhance-the-form-with-the-useactionstate-hook">Enhance the Form with the <code>useActionState</code> Hook</h3>
<p>First, import the <code>useActionState</code> and <code>useEffect</code> hooks into the <code>message-form.jsx</code> file. Also, import the <code>toast</code> from <code>sonner</code>. As we will be using the hooks now, we have to make the <code>message-form</code> component a client component. So, add the <code>”use client”</code> directive at the top of the file.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use client"</span>;

<span class="hljs-keyword">import</span> Form <span class="hljs-keyword">from</span> <span class="hljs-string">"next/form"</span>;
<span class="hljs-keyword">import</span> { useActionState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { sendDiscordMessage } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>;
<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { toast } <span class="hljs-keyword">from</span> <span class="hljs-string">"sonner"</span>;
</code></pre>
<p>Next, use the <code>useActionState</code> hook to get the <code>formState</code> updated from the server action result. An <code>isPending</code> state tells us if the form submission has been completed. The <code>useActionState</code> returns a new <code>formAction</code> from the existing server action instance.</p>
<p>The syntax goes like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [formState, formAction, isPending] = useActionState(sendDiscordMessage,<span class="hljs-literal">null</span>);
</code></pre>
<p>Now, we need to use this <code>formAction</code> as the value of the <code>action</code> attribute of the <code>&lt;Form /&gt;</code> component:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{formAction}</span>&gt;</span>
</code></pre>
<p>Next, use the <code>useEffect</code> hook to track the <code>formState</code> changes and show the toast message accordingly. The shape of the <code>formState</code> can be customized based on our needs. We will see shortly how the server action can return this state value.</p>
<pre><code class="lang-javascript">  useEffect (<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (formState?.success) {
      toast.success(formState?.message);
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (formState?.success === <span class="hljs-literal">false</span>) {
      toast.error(formState?.message);
    }
  },[formState?.success])
</code></pre>
<p>The last thing here is to improve the UX of the form using the <code>isPending</code> state we got from the <code>useActionState</code> hook. The value of the <code>isPending</code> state will be true if the form is still in transition and being submitted. It will be changed to false when the form is submitted. So we can use the state value to customize the submit button text.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>
  <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>
  <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-blue-500 w-[70px] text-white rounded-md"</span>&gt;</span>
    {isPending ? "Sending..." : "Send"}
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>Those are all the changes we need to make in the form component. Here’s the complete code of the modified form component for you to check out and use:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use client"</span>;

<span class="hljs-keyword">import</span> Form <span class="hljs-keyword">from</span> <span class="hljs-string">"next/form"</span>;
<span class="hljs-keyword">import</span> { useActionState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { sendDiscordMessage } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>;
<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>
<span class="hljs-keyword">import</span> { toast } <span class="hljs-keyword">from</span> <span class="hljs-string">"sonner"</span>;

<span class="hljs-keyword">const</span> MessageForm = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [formState, formAction, isPending] = useActionState(
    sendDiscordMessage,
    <span class="hljs-literal">null</span>
  );

  useEffect (<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (formState?.success) {
      toast.success(formState?.message);
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (formState?.success === <span class="hljs-literal">false</span>) {
      toast.error(formState?.message);
    }
  },[formState?.success])



  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col items-center"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{formAction}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your name"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-1 rounded w-[300px] my-2"</span>
        <span class="hljs-attr">required</span>
      /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your e-mail"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-1 rounded w-[300px] my-2"</span>
        <span class="hljs-attr">required</span>
      /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your Image Url"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"dp"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-1 rounded w-[300px] my-2"</span>
      /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">select</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"type"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"p-1 rounded border my-2 w-[300px]"</span>
        <span class="hljs-attr">required</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span>Message Type<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"thanks"</span>&gt;</span>Say, Thanks!<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"qa"</span>&gt;</span>QA<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"general"</span>&gt;</span>General<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
        <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"What do you want to say?"</span>
        <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-1 rounded w-[300px] my-2"</span>
        <span class="hljs-attr">required</span>
      /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-blue-500 w-[70px] text-white rounded-md"</span>
      &gt;</span>
        {isPending ? "Sending..." : "Send"}
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Form</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MessageForm;
</code></pre>
<h3 id="heading-how-to-update-the-server-action-to-return-results">How to Update the Server Action to Return Results</h3>
<p>The changes in the server action should be as follows:</p>
<ol>
<li><p>When you use the <code>useActionState</code> hook, pass a returned <code>formAction</code> to the form. We have seen this before. It helps in multiple ways, and one of them is getting the previous state value of the <code>formState</code> inside the server action. You must be mindful to pass it as the first argument to the server function, and then the <code>formData</code>.</p>
</li>
<li><p>We can now return the result of the server action so that the <code>formState</code> gets updated with the result. We will create a result structure with a boolean <code>success</code> field indicating if it is a success or error scenario and a <code>message</code> field with the actual message.</p>
</li>
</ol>
<p>Here’s the changed code with the above two updates:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> sendDiscordMessage = <span class="hljs-keyword">async</span> (prevState, formData) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> rawFormEntries = <span class="hljs-built_in">Object</span>.fromEntries(formData);

    <span class="hljs-built_in">console</span>.log(rawFormEntries);

    <span class="hljs-keyword">await</span> fetch(process.env.DISCORD_WEBHOOK_URL, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
      <span class="hljs-attr">headers</span>: {
        <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
      },
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        <span class="hljs-attr">username</span>: rawFormEntries?.username,
        <span class="hljs-attr">avatar_url</span>: rawFormEntries?.dp || <span class="hljs-string">"https://i.imgur.com/mDKlggm.png"</span>,
        <span class="hljs-attr">content</span>: rawFormEntries?.message,
        <span class="hljs-attr">embeds</span>: [
          {
            <span class="hljs-attr">fields</span>: [
              {
                <span class="hljs-attr">name</span>: <span class="hljs-string">"Email"</span>,
                <span class="hljs-attr">value</span>: rawFormEntries?.email,
                <span class="hljs-attr">inline</span>: <span class="hljs-literal">true</span>,
              },
              {
                <span class="hljs-attr">name</span>: <span class="hljs-string">"Message Type"</span>,
                <span class="hljs-attr">value</span>: rawFormEntries?.type,
                <span class="hljs-attr">inline</span>: <span class="hljs-literal">true</span>,
              },
            ],
          },
        ],
      }),
    });

    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">success</span>: <span class="hljs-literal">true</span>,
      <span class="hljs-attr">message</span>: <span class="hljs-string">`Your message has been sent successfully.`</span>,
    };
  } <span class="hljs-keyword">catch</span> (err) {
    <span class="hljs-built_in">console</span>.log(err.message);
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">success</span>: <span class="hljs-literal">false</span>,
      <span class="hljs-attr">message</span>: <span class="hljs-string">`Problem is sending message <span class="hljs-subst">${err.message}</span>`</span>,
    };
  }
};
</code></pre>
<p>As you must have noticed, the returned result is the <code>formState</code> we have used inside the <code>form</code> component to show the toast messages.</p>
<h2 id="heading-lets-test-it-one-more-time">Let’s Test it One More Time</h2>
<p>Let’s test things out with all the changes.</p>
<ol>
<li>First, fill out the form with the details. Now we’re using a profile picture URL rather than keeping it empty. Click on the <code>Send</code> button.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736922583168/b044cca3-bb45-48d2-83bc-ec9459d86206.png" alt="Updated Form" class="image--center mx-auto" width="901" height="594" loading="lazy"></p>
<ol start="2">
<li>You should see the that button text gets changed to <code>Sending…</code> while the form is being submitted.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736922728585/afdbe8cc-fdc3-4be1-8676-ffed5160168a.png" alt="Sending State" class="image--center mx-auto" width="703" height="574" loading="lazy"></p>
<ol start="3">
<li>After the submission, you should get the success message in the toast. Also, the form state should be restored to its original state.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736922801497/518fa3ec-16d1-44a7-aa42-a647512379b5.png" alt="Success Message" class="image--center mx-auto" width="1426" height="1136" loading="lazy"></p>
<ol start="4">
<li>On the Discord text channel, you should see the message posted successfully.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736922367821/41cd6329-b6e5-45e7-8674-df7cff8e932d.png" alt="Updated message" class="image--center mx-auto" width="848" height="366" loading="lazy"></p>
<p>That’s amazing! We have now made the app much better with the message and error handling.</p>
<h2 id="heading-source-code-and-resources">Source Code and Resources</h2>
<p>All the source code used in this article is in the GitHub repository. You can take a look, follow the README to set it up, and run it locally.</p>
<ul>
<li><a target="_blank" href="https://github.com/tapascript/next-js-discord">The next-js-discord GitHub repository</a></li>
</ul>
<p>Here are the resources I mentioned in the article that you may find helpful:</p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=vl_aGFMShg0">Next.js 15 Form Component - All That You Need To Know</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=gQ2bVQPFS4U">Next.js Server Actions || Learn Patterns &amp; Project Building</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=PWFKgdGmhxg">MASTER React 19 useActionState Hook with Project &amp; Usecases</a></p>
</li>
<li><p><a target="_blank" href="https://react.dev/reference/react/useActionState">The useActionState official doc</a></p>
</li>
</ul>
<p>Also, you can connect with me by:</p>
<ul>
<li><p>Subscribing to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>. If you are willing to learn <code>React</code> and its ecosystem, like <code>Next.js</code>, with both fundamental concepts and projects, I have great news for you: you can <a target="_blank" href="https://www.youtube.com/watch?v=VSB2h7mVhPg&amp;list=PLIJrr73KDmRwz_7QUvQ9Az82aDM9I8L_8">check out this playlist on my YouTube</a> channel with 30+ video tutorials and 20+ hours of engaging content so far, for free. I hope you like them as well.</p>
</li>
<li><p><a target="_blank" href="https://twitter.com/tapasadhikary">Following me on X (Twitter</a>) or <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Checking out and following my Open Source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</p>
</li>
<li><p>I regularly publish meaningful posts on my <a target="_blank" href="https://blog.greenroots.info/">GreenRoots Blog</a>, you may find them helpful, too.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself, and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Pass Additional Arguments to Next.js Server Actions ]]>
                </title>
                <description>
                    <![CDATA[ Asynchronous data mutation and handling is a necessary task in modern web applications. You may want to execute a standalone asynchronous function on the server to carryout tasks like saving data to the data store, sending emails, downloading PDFs, p... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-pass-additional-arguments-to-nextjs-server-actions/</link>
                <guid isPermaLink="false">6717fde839354c63841ba816</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ server actions ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Tue, 22 Oct 2024 19:32:56 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729165969570/14ca2ef4-8a08-40f8-ba70-c6c24c194850.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Asynchronous data mutation and handling is a necessary task in modern web applications. You may want to execute a standalone asynchronous function on the server to carryout tasks like saving data to the data store, sending emails, downloading PDFs, processing images, and so on.</p>
<p>Next.js provides us with <code>Server Actions</code> which are asynchronous functions that execute on the server. We can use server actions for data mutations on the server, but server actions can be invoked from both server and client components.</p>
<p>Server actions are a great way to handle form submissions by executing the action when the form data gets submitted. In this article, we will look into a practical use case of handling additional arguments in Next.js server actions.</p>
<p>If you are interested in learning Next.js Server Actions with design patterns and project building, I have created a crash course for you that you can find <a target="_blank" href="https://www.youtube.com/watch?v=gQ2bVQPFS4U">here</a>.</p>
<p>Also, this article is also available as a video tutorial here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9PBtj0sUc7Q" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-why-would-you-need-to-pass-additional-arguments">Why Would You Need to Pass Additional Arguments?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-form-with-a-server-action">A Form with a Server Action</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-pass-additional-arguments">How to Pass Additional Arguments</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-about-the-hidden-fields">What About the Hidden Fields?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-resources">Resources</a></p>
</li>
</ol>
<h2 id="heading-why-would-you-need-to-pass-additional-arguments">Why Would You Need to Pass Additional Arguments?</h2>
<p>When we execute a server action on a form submission, the server action gets the form data automatically. For example, take a look at the form below:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 flex"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{updateUser}</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Input</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-1/2 mx-2"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Update User Name<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>Here, we are executing a server action called <code>updateUser</code> when the form gets submitted. The <code>updateUser</code> function will receive the submitted form data as an argument which can be used to extract the form field values.</p>
<p>As you see in the code snippet below, the <code>updateUser</code> function gets a <code>formData</code> as an argument, and we can extract the value of the <code>name</code> field from it.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUser</span>(<span class="hljs-params">formData</span>) </span>{
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">'name'</span>);
  <span class="hljs-built_in">console</span>.log(name);
}
</code></pre>
<p>While this pattern covers most of the basic use cases, you may need to pass additional arguments programmatically to the server actions. These arguments are not part of the form or form data or user input data. They may be programmatically passed values to your server action.</p>
<p>To understand this, check the server action code snippet below. It’s the same server action we have seen before, but we have passed an additional <code>userId</code> argument along with the regular <code>formData</code> argument.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUser</span>(<span class="hljs-params">userId, formData</span>) </span>{
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">'name'</span>);
  <span class="hljs-built_in">console</span>.log(userId);
  <span class="hljs-built_in">console</span>.log(name);
}
</code></pre>
<p>The <code>userId</code> value is something internal to the application – and you wouldn’t ask a user to submit the value as part of the form submission. Rather, you may need to pass it programmatically to your server action to perform further computations.</p>
<p>Right, that’s the use case we’re talking about. As we understand why we need it, let’s understand how to achieve it. But first, let’s create a form and a working server action for it.</p>
<h2 id="heading-a-form-with-a-server-action">A Form With a Server Action</h2>
<p>Create a directory called <code>actions</code> under the <code>app</code> directory of your Next.js application. Now create a <code>user.js</code> file under the <code>actions</code> folder with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUser</span>(<span class="hljs-params">formData</span>) </span>{
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">'name'</span>);
  <span class="hljs-built_in">console</span>.log(name);

  <span class="hljs-comment">// Do anything with the name, save in DB, create invoice, whatever!</span>
}
</code></pre>
<p>This is how you create a server function in Next.js. It must have a <code>”use server”</code> directive at the top of the file to tell Next.js that this is a special file with one or more asynchronous functions to execute on the server.</p>
<p>Then we have the server action (the async function) <code>updateUser</code> with <code>formData</code> as the argument. Inside the function definition, we extract out the <code>name</code> value and print it on the console.</p>
<p>Let’s now attach this server action to a form. To do that, create a folder called <code>components</code> under the project root folder. Create a file called <code>user-form.jsx</code> with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Input } <span class="hljs-keyword">from</span> <span class="hljs-string">"./ui/input"</span>
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">"./ui/button"</span>

<span class="hljs-keyword">import</span> { updateUser } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/app/actions/user"</span>

<span class="hljs-keyword">const</span> UserForm = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span>(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 flex"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{updateUser}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Input</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-1/2 mx-2"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Update User Name<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UserForm;
</code></pre>
<p>This is a simple React component with a form. The form has one input text field called <code>name</code> and a submit button to submit the form. The form has an <code>action</code> attribute with the server action <code>updateUser</code> as the value. Now, when the form gets submitted with a <code>name</code> value, the server action will get it as part of the form data as we discussed above.</p>
<p>Let’s test it out. To do that, we’ll create a Next.js route and page where we can use the <code>UserForm</code> component. Create a folder called <code>extra-args</code> under the <code>app</code> directory. Now, create a file called <code>page.js</code> under the <code>app/extra-args</code> directory with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> UserForm <span class="hljs-keyword">from</span> <span class="hljs-string">"@/components/user-form"</span>;

<span class="hljs-keyword">const</span> ExtraArgsDemo = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserForm</span> /&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExtraArgsDemo;
</code></pre>
<p>This is a simple React component where we have imported the <code>UserForm</code> component and used it in the JSX. Now run the local server and access this route <code>localhost:3000/extra-args</code>. You should see the form with a text field and a button.</p>
<p>Type some text inside the text field and click on the button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729167845597/b4c58399-4188-4b89-8ec7-dd2602c10ccd.png" alt="Application with server actions" class="image--center mx-auto" width="1534" height="824" loading="lazy"></p>
<p>Now, you will be able to see that the typed text has been printed on the server console. Why on the server console? Why not on the browser console? This is because server actions execute on the server, not on the client side browser.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729167722231/e8c40a4d-e506-42fb-8ea3-233e295ac534.png" alt="Output Mike" class="image--center mx-auto" width="900" height="408" loading="lazy"></p>
<p>So, with this we have now established a data flow like this:</p>
<p>Page =&gt; Form =&gt; Server Action</p>
<p>The page has a form. The form execute a server action on submission. The server action prints a form data on the server console.</p>
<p>Let’s now enhance these pieces to pass additional arguments to the server action.</p>
<h2 id="heading-how-to-pass-additional-arguments">How to Pass Additional Arguments</h2>
<p>Let’s pass a prop to the <code>UserForm</code> component from the page. We’ll pass a <code>userId</code> with a value to pretend that we are passing this userId programmatically to our form and to the server action from there.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> UserForm <span class="hljs-keyword">from</span> <span class="hljs-string">"@/components/user-form"</span>;

<span class="hljs-keyword">const</span> ExtraArgsDemo = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UserForm</span> <span class="hljs-attr">userId</span>=<span class="hljs-string">{</span>"<span class="hljs-attr">1234</span>"} /&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ExtraArgsDemo;
</code></pre>
<p>In the <code>UserForm</code> component, we accept the <code>userId</code> prop. Now, we have to do something special to pass this userId to the <code>updateUser</code> server action.</p>
<p>JavaScript has a magical method called <code>bind()</code> that helps us create a <code>Partially Applied Function</code>. With this <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#partially_applied_functions">partially applied function</a>, you can create a function from another function’s preset arguments.</p>
<p>In our case, the <code>updateUser</code> function already has an argument called <code>formData</code>. Now we can pass <code>userId</code> as the additional argument using the <code>bind()</code> method to create a new function.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> updatedUserWithId = updateUser.bind(<span class="hljs-literal">null</span>, userId);
</code></pre>
<p>The first argument of the <code>bind()</code> method is the context you are binding the function to. The context handles the association of the function with the <code>this</code> keyword value. In our case, we can keep it <code>null</code> as we are not changing it. After that, we passed the new argument <code>userId</code>. It’s good to know that the <code>bind()</code> method works on both server and client components.</p>
<p>Here is the modified <code>UserForm</code> component (<code>user-form.jsx</code> file). Note that the form action value is now modified to the new function <code>updatedUserWithId</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Input } <span class="hljs-keyword">from</span> <span class="hljs-string">"./ui/input"</span>
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">"./ui/button"</span>

<span class="hljs-keyword">import</span> { updateUser } <span class="hljs-keyword">from</span> <span class="hljs-string">"@/app/actions/user"</span>

<span class="hljs-keyword">const</span> UserForm = <span class="hljs-function">(<span class="hljs-params">{userId}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> updatedUserWithId = updateUser.bind(<span class="hljs-literal">null</span>, userId);

  <span class="hljs-keyword">return</span>(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"p-4 flex"</span> <span class="hljs-attr">action</span>=<span class="hljs-string">{updatedUserWithId}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Input</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-1/2 mx-2"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Update User Name<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> UserForm;
</code></pre>
<p>Now, the server action will receive the <code>userId</code> value as an argument. Let’s print that to the console as well.</p>
<pre><code class="lang-javascript"><span class="hljs-string">"use server"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUser</span>(<span class="hljs-params">userId, formData</span>) </span>{
  <span class="hljs-keyword">const</span> name = formData.get(<span class="hljs-string">'name'</span>);
  <span class="hljs-built_in">console</span>.log(userId);
  <span class="hljs-built_in">console</span>.log(name);

  <span class="hljs-comment">// Do anything with the user id and name, save in DB, </span>
  <span class="hljs-comment">// create invoice, whatever!</span>
}
</code></pre>
<p>Now if you submit the form with a name value:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729167845597/b4c58399-4188-4b89-8ec7-dd2602c10ccd.png" alt="Application with server actions again" class="image--center mx-auto" width="1534" height="824" loading="lazy"></p>
<p>You’ll see that both userId and the name values are logged into the server console. Great! We have logged one value from the form data, and the other one was passed internally to the server action.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729169164296/d0ef49f8-88bc-4e82-a509-cbb859df87e1.png" alt="d0ef49f8-88bc-4e82-a509-cbb859df87e1" class="image--center mx-auto" width="830" height="312" loading="lazy"></p>
<p>So, we learned how to pass the extra arguments to the server action along with the form data.</p>
<h2 id="heading-what-about-the-hidden-fields">What About the Hidden Fields?</h2>
<p>HTML supports a hidden type form field to pass client data to the server without accepting the input from the users. So this means that we could have used the hidden field to pass the <code>userId</code> value like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729485711865/21f33410-fcdd-46ea-b14c-d57004b30a96.png" alt="hidden field" class="image--center mx-auto" width="744" height="151" loading="lazy"></p>
<p>So why did we do all that with the <code>bind()</code> method? Well, because of security concerns. When you pass data using hidden fields, the value will be part of the rendered HTML, and it will not be encoded as well. So it’s better to handle it programmatically.</p>
<h2 id="heading-resources">Resources</h2>
<p>That's all for now. Did you enjoy reading this article and have you learned something new? If so, I would love to know if the content was helpful. Let me share a few additional resources you may need:</p>
<ul>
<li><p>All the Source Code used in this article is <a target="_blank" href="https://github.com/atapas/nextjs-email/tree/extra-arg">on my GitHub</a>.</p>
</li>
<li><p>Here’s the <a target="_blank" href="https://www.youtube.com/watch?v=gQ2bVQPFS4U">Server Action Crash Course with Patterns and Project</a>.</p>
</li>
<li><p>Here’s the <a target="_blank" href="https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations">Server Action Official Documentation</a> if you want to read more.</p>
</li>
<li><p>And you can read more about the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">bind() method here</a>.</p>
</li>
</ul>
<p>Additionally, you can connect with me by:</p>
<ul>
<li><p>Subscribing to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>. If you are willing to learn <code>React</code> and its ecosystem, like <code>Next.js</code>, with both fundamental concepts and projects, I have great news for you: you can <a target="_blank" href="https://www.youtube.com/watch?v=VSB2h7mVhPg&amp;list=PLIJrr73KDmRwz_7QUvQ9Az82aDM9I8L_8">check out this playlist on my YouTube</a> channel with 25+ video tutorials and 15+ hours of engaging content so far, for free. I hope you like them as well.</p>
</li>
<li><p><a target="_blank" href="https://twitter.com/tapasadhikary">Following me on X (Twitter</a>) or <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Checking out and follow my Open Source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</p>
</li>
<li><p>I regularly publish meaningful posts on my <a target="_blank" href="https://blog.greenroots.info/">GreenRoots Blog</a>, you may find them helpful, too.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself, and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use React Compiler – A Complete Guide ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you'll learn how the React compiler can help you write more optimized React applications. React is a user interface library that has been doing its job quite well for over a decade. The component architecture, uni-directional data f... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/react-compiler-complete-guide-react-19/</link>
                <guid isPermaLink="false">66ce54c3e498db1304d6a34b</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React 19 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React-compiler ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Tue, 27 Aug 2024 22:35:47 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724760187590/f7115fd3-6291-4920-9522-61de269a47f3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you'll learn how the React compiler can help you write more optimized React applications.</p>
<p>React is a user interface library that has been doing its job quite well for over a decade. The component architecture, uni-directional data flow, and declarative nature stand out in helping devs building production-ready, scalable software applications.</p>
<p>Over the releases (even up until the latest stable release of v18.x), React has provided various techniques and methodologies to improve application performance.</p>
<p>For example, the entire memoization paradigm has been supported using the <code>React.memo()</code> higher-order component, or with hooks like <code>useMemo()</code> and <code>useCallback()</code>.</p>
<p>In programming, <code>memoization</code> is an optimization technique that makes your programs execute faster by caching the result of expensive computations.</p>
<p>Although React's <code>memoization</code> techniques are great for applying optimizations, as Uncle Ben (remember, Spiderman's uncle?) once said, "With great power comes great responsibility". So we as developers need to be a little more responsible in applying them. Optimization is great, but over-optimization can be a killer for the application's performance.</p>
<p>With React 19, the developer community has received a list of enhancements and features to boast about:</p>
<ul>
<li><p>An experimental open-source compiler. We will be focusing primarily on it in this article.</p>
</li>
<li><p>React Server Components.</p>
</li>
<li><p>Server Actions.</p>
</li>
<li><p>Easier and more organic way of handling the document metadata.</p>
</li>
<li><p>Enhanced hooks and APIs.</p>
</li>
<li><p><code>ref</code> can be passed as props.</p>
</li>
<li><p>Improvements in asset loading for styles, images, and fonts.</p>
</li>
<li><p>A much smoother integration with Web Components.</p>
</li>
</ul>
<p>If these are exciting to you, I recommend <a target="_blank" href="https://www.youtube.com/watch?v=hiiGUjEkzbM">watching this video</a> that explains how each feature will impact you as a React developer. I hope you like it 😊.</p>
<p>The introduction of a <code>compiler</code> with <code>React 19</code> is set to be a game-changer. From now on, we can let the compiler handle the optimization headache rather than keeping it on us.</p>
<p>Does this mean we do not have to use <code>memo</code>, <code>useMemo()</code>, <code>useCallback</code>, and so on anymore? No – we mostly don't. The compiler can take care of these things automatically if you understand and follow the <a target="_blank" href="https://react.dev/reference/rules">Rules of React</a> for components and hooks.</p>
<p>How will it do this? Well, we'll get to it. But before that, let's understand what a <code>compiler</code> is and whether it's justified to call this new optimizer for React code the <code>React Compiler</code>.</p>
<p>If you like to learn from video tutorials as well, this article is also available as a video tutorial here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/bdWUVp0TbTU" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-a-compiler-traditionally">What is a Compiler, traditionally?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-react-compiler-architecture">React Compiler Architecture</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-react-compiler-in-action">React Compiler in action</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-problem-without-the-react-compiler">Understanding the problem: Without the React Compiler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-fixing-the-problem-without-the-react-compiler">Fixing the problem: Without the React Compiler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-fixing-the-problem-using-the-react-compiler">Fixing the problem: Using the React Compiler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-optimized-react-app-with-react-compiler">Optimized React App with React Compiler</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-react-compiler-in-react-devtools">React Compiler in React DevTools</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-diving-deep-how-does-the-react-compiler-work">Diving deep - How does the React Compiler work?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-do-you-opt-in-and-out-of-the-react-compiler">How do you opt in and out of the React compiler?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-can-we-use-the-react-compiler-with-react-18x">Can we use the React Compiler with React 18.x?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-repositories-to-look-into">Repositories to look into</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-whats-next">What's Next?</a></p>
</li>
</ol>
<h2 id="heading-what-is-a-compiler-traditionally">What is a Compiler, Traditionally?</h2>
<p>Simply put, a compiler is a software program/tool that translates high-level programming language code (source code) into machine code. There are several steps to follow to compile source code and generate machine code:</p>
<ul>
<li><p>The <code>lexical analyzer</code> tokenizes the source code and generates tokens.</p>
</li>
<li><p>The <code>Syntax Analyzer</code> creates an abstract syntax tree (AST) to structure the source code tokens logically.</p>
</li>
<li><p>The <code>Semantic Analyzer</code> validates the semantic (or syntactic) correctness of the code.</p>
</li>
<li><p>After all three types of analysis by the respective analyzers, some <code>intermediate code</code> gets generated. It is also known as the IR code.</p>
</li>
<li><p>Then <code>optimization</code> is performed on the IR code.</p>
</li>
<li><p>Finally, the <code>machine code</code> is generated by the compiler from the optimized IR code.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724227359567/a3994e4c-9018-4b67-94be-8b5f403eceb9.png" alt="Compiler phases as described above" class="image--center mx-auto" width="1200" height="630" loading="lazy"></p>
<p>Now that you understand the basics of how a compiler works, let's learn about the <code>React Compiler</code> and understand how it works.</p>
<h2 id="heading-react-compiler-architecture">React Compiler Architecture</h2>
<p>React compiler is a build-time tool that you need to configure with your React 19 project explicitly using the configuration options provided by the React tools ecosystem.</p>
<p>For example, if you are using <code>Vite</code> to create your React application, the compiler configuration will take place in the <code>vite.config.js</code> file.</p>
<p>React compiler has three primary components:</p>
<ol>
<li><p><code>Babel Plugin</code><strong>:</strong> helps transform the code during the compilation process<strong>.</strong></p>
</li>
<li><p><code>ESLint Plugin</code><strong>:</strong> helps catch and report any violations of the Rules of React.</p>
</li>
<li><p><code>Compiler Core</code>: the core compiler logic that performs the code analysis and optimizations. Both Babel and ESLint plugins use the core compiler logic.</p>
</li>
</ol>
<p>The compilation flow goes like this:</p>
<ul>
<li><p>The <code>Babel Plugin</code> identifies which functions (components or hooks) to compile. We will see some configurations later to learn how to opt in and out of the compilation process. The plugin calls the core compiler logic for each of the functions and finally creates the Abstract Syntax Tree.</p>
</li>
<li><p>Then the compiler core converts the Babel AST into IR code, analyzes it, and runs various validations to ensure none of the rules are broken.</p>
</li>
<li><p>Next, it tries to reduce the amount of code to be optimized by performing various passes to eliminate dead code. The code gets further optimized using memoization.</p>
</li>
<li><p>Finally, in the code generation stage, the transformed AST is converted back to the optimized JavaScript code.</p>
</li>
</ul>
<h2 id="heading-react-compiler-in-action">React Compiler in Action</h2>
<p>Now that you know how React Compiler works, let's now dive into configuring it with a React 19 project so you can start learning about the various optimizations.</p>
<h3 id="heading-understanding-the-problem-without-the-react-compiler">Understanding the problem: Without the React Compiler</h3>
<p>Let's create a simple product page with React. The product page shows a heading with the number of products on the page, a list of products, and the featured products.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724240252940/bd5118d1-2819-4119-ac96-57e267742432.png" alt="The Product Page" class="image--center mx-auto" width="744" height="914" loading="lazy"></p>
<p>The component hierarchy and the data passing between the components look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724240027326/0a8a653d-9c6a-43ff-9457-81dde019e56e.png" alt="Product Page Component Hierarchy" class="image--center mx-auto" width="1456" height="976" loading="lazy"></p>
<p>As you can see in the image above,</p>
<ul>
<li><p>The <code>ProductPage</code> component has three child components, <code>Heading</code>, <code>ProductList</code>, and <code>FeaturedProducts</code>.</p>
</li>
<li><p>The <code>ProductPage</code> component receives two props, <code>products</code> and the <code>heading</code>.</p>
</li>
<li><p>The <code>ProductPage</code> component computes the total number of products and passes the value along with the heading text value to the <code>Heading</code> component.</p>
</li>
<li><p>The <code>ProductPage</code> component passes down the <code>products</code> prop to the <code>ProductList</code> child component.</p>
</li>
<li><p>Similarly, it computes the featured products and passes the <code>featuredProducts</code> prop to the <code>FeaturedProducts</code> child component.</p>
</li>
</ul>
<p>Here is how the source code of the <code>ProductPage</code> component may look:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">import</span> Heading <span class="hljs-keyword">from</span> <span class="hljs-string">'./Heading'</span>;
<span class="hljs-keyword">import</span> FeaturedProducts <span class="hljs-keyword">from</span> <span class="hljs-string">'./FeaturedProducts'</span>;
<span class="hljs-keyword">import</span> ProductList <span class="hljs-keyword">from</span> <span class="hljs-string">'./ProductList'</span>;

<span class="hljs-keyword">const</span> ProductPage = <span class="hljs-function">(<span class="hljs-params">{products, heading}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> featuredProducts = products.filter(<span class="hljs-function"><span class="hljs-params">product</span> =&gt;</span> product.featured);
  <span class="hljs-keyword">const</span> totalProducts = products.length;

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"m-2"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Heading</span>
        <span class="hljs-attr">heading</span>=<span class="hljs-string">{heading}</span>
        <span class="hljs-attr">totalProducts</span>=<span class="hljs-string">{totalProducts}</span> /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">ProductList</span>
        <span class="hljs-attr">products</span>=<span class="hljs-string">{products}</span> /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">FeaturedProducts</span>
        <span class="hljs-attr">featuredProducts</span>=<span class="hljs-string">{featuredProducts}</span> /&gt;</span>  

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ProductPage
</code></pre>
<p>Also, assume we use the <code>ProductPage</code> component in the <code>App.js</code> file like this:</p>
<pre><code class="lang-javascript">
<span class="hljs-keyword">import</span> ProductPage <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/compiler/ProductPage"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-comment">// A list of food products    </span>
  <span class="hljs-keyword">const</span> foodProducts = [
    {
      <span class="hljs-string">"id"</span>: <span class="hljs-string">"001"</span>,
      <span class="hljs-string">"name"</span>: <span class="hljs-string">"Hamburger"</span>,
      <span class="hljs-string">"image"</span>: <span class="hljs-string">"🍔"</span>,
      <span class="hljs-string">"featured"</span>: <span class="hljs-literal">true</span>
    },
    {
      <span class="hljs-string">"id"</span>: <span class="hljs-string">"002"</span>,
      <span class="hljs-string">"name"</span>: <span class="hljs-string">"French Fries"</span>,
      <span class="hljs-string">"image"</span>: <span class="hljs-string">"🍟"</span>,
      <span class="hljs-string">"featured"</span>: <span class="hljs-literal">false</span>
    },
    {
      <span class="hljs-string">"id"</span>: <span class="hljs-string">"003"</span>,
      <span class="hljs-string">"name"</span>: <span class="hljs-string">"Taco"</span>,
      <span class="hljs-string">"image"</span>: <span class="hljs-string">"🌮"</span>,
      <span class="hljs-string">"featured"</span>: <span class="hljs-literal">false</span>
    },
    {
      <span class="hljs-string">"id"</span>: <span class="hljs-string">"004"</span>,
      <span class="hljs-string">"name"</span>: <span class="hljs-string">"Hot Dog"</span>,
      <span class="hljs-string">"image"</span>: <span class="hljs-string">"🌭"</span>,
      <span class="hljs-string">"featured"</span>: <span class="hljs-literal">true</span>
    }
  ];

  <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ProductPage</span> 
            <span class="hljs-attr">products</span>=<span class="hljs-string">{foodProducts}</span> 
            <span class="hljs-attr">heading</span>=<span class="hljs-string">"The Food Product"</span> /&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>That's all good – so where is the problem? The problem is that React proactively re-renders the child component when the parent component re-renders. An unnecessary rendering requires optimizations. Let's understand the problem fully first.</p>
<p>We'll add the current timestamp in each of the child components. Now the rendered user interface will look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724241332454/5debcdce-0349-40a3-916f-78e479668c12.png" alt="With timestamp" class="image--center mx-auto" width="1374" height="926" loading="lazy"></p>
<p>The big number you see beside the headings is the timestamp (using the simple <code>Date.now()</code> function from the JavaScript Date API) we have added to the component code. Now what happens if we change the value of the heading prop of the <code>ProductPage</code> component?</p>
<p>Before:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">ProductPage</span> 
   <span class="hljs-attr">products</span>=<span class="hljs-string">{foodProducts}</span> 
   <span class="hljs-attr">heading</span>=<span class="hljs-string">"The Food Product"</span> /&gt;</span>
</code></pre>
<p>And after (notice that we have made it plural for products by adding an <code>s</code> at the end of the <code>heading</code> value):</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">ProductPage</span> 
   <span class="hljs-attr">products</span>=<span class="hljs-string">{foodProducts}</span> 
   <span class="hljs-attr">heading</span>=<span class="hljs-string">"The Food Products"</span> /&gt;</span>
</code></pre>
<p>Now you will notice an immediate change in the user interface. All three timestamps got updated. This is because all three components were re-rendered when the parent component was re-rendered due to the props change.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724242207319/b3f2aa7e-d387-4de4-a2e6-9491f5cf7996.png" alt="compiler diff" class="image--center mx-auto" width="1200" height="630" loading="lazy"></p>
<p>If you notice, the <code>heading</code> prop was passed only to the <code>Heading</code> component, and even then the other two child components re-rendered. This is where we need the optimizations.</p>
<h3 id="heading-fixing-the-problem-without-the-react-compiler">Fixing the Problem: Without the React Compiler</h3>
<p>As discussed before, React provides us with various hooks and APIs for <code>memoization</code>. We can use <code>React.memo()</code> or <code>useMemo()</code> to safeguard the components that are re-rendering unnecessarily.</p>
<p>For example, we can use <code>React.memo()</code> to memoize the ProductList component to ensure that unless the <code>products</code> prop is changed, the <code>ProductList</code> component will not be re-rendered.</p>
<p>We can use the <code>useMemo()</code> hook to memoize the computation for the featured products. Both implementations are indicated in the image below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724242889553/ec0d54fc-8c50-4fef-a4ea-e8c5951da9ad.png" alt="Applying memoization" class="image--center mx-auto" width="2462" height="1318" loading="lazy"></p>
<p>But again, recollecting the wise words of great Uncle Ben, over the last few years we have started over-using these optimization techniques. These over-optimizations can negatively impact the performance of your applications. So, the availability of the compiler is a boon for React developers as it lets them delegate many such optimizations to the compiler.</p>
<p>Let's now fix the problem using the React compiler.</p>
<h3 id="heading-fixing-the-problem-using-the-react-compiler">Fixing the problem: Using the React Compiler</h3>
<p>Again, React compiler is an opt-in build-time tool. It doesn't come bundled with React 19 RC. You need to install the required dependencies and configure the compiler with your React 19 project.</p>
<p>Before configuring the compiler, you can check if your codebase is compatible by executing this command on your project directory:</p>
<pre><code class="lang-bash">npx react-compiler-healthcheck@experimental
</code></pre>
<p>It will check and report:</p>
<ul>
<li><p>How many components can be optimized by the compiler</p>
</li>
<li><p>If the Rules of React are followed.</p>
</li>
<li><p>If there are any incompatible libraries.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724300204675/d7866215-5cda-4a64-b0d6-ecedb100a428.png" alt="d7866215-5cda-4a64-b0d6-ecedb100a428" class="image--center mx-auto" width="1832" height="448" loading="lazy"></p>
<p>If you find that things are compatible, it's time to install the ESLint plugin powered by the React compiler. This plugin will help you catch any violation of the rules of React in your code. Violating code will be skipped by the React compiler and no optimizations will be performed on it.</p>
<pre><code class="lang-bash">npm install eslint-plugin-react-compiler@experimental
</code></pre>
<p>Then open the ESLint configuration file (for example, <code>.eslintrc.cjs</code> for Vite) and add these configurations:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">plugins</span>: [
    <span class="hljs-string">'eslint-plugin-react-compiler'</span>,
  ],
  <span class="hljs-attr">rules</span>: {
    <span class="hljs-string">'react-compiler/react-compiler'</span>: <span class="hljs-string">"error"</span>,
  },
}
</code></pre>
<p>Next, you'll use the Babel plugin for the React compiler to enable the compiler for your entire project. If you're starting a new project with React 19, I recommend that you enable the React compiler for the entire project. Let's install the Babel plugin for the React compiler:</p>
<pre><code class="lang-bash">npm install babel-plugin-react-compiler@experimental
</code></pre>
<p>Once installed, you need to complete the configuration by adding the options in the Babel config file. As we're using Vite, open the <code>vite.config.js</code> file and replace the content with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>
<span class="hljs-keyword">import</span> react <span class="hljs-keyword">from</span> <span class="hljs-string">'@vitejs/plugin-react'</span>

<span class="hljs-keyword">const</span> ReactCompilerConfig = {<span class="hljs-comment">/* ... */</span> };

<span class="hljs-comment">// https://vitejs.dev/config/</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">plugins</span>: [react({
    <span class="hljs-attr">babel</span>: {
      <span class="hljs-attr">plugins</span>: [
        [
          <span class="hljs-string">"babel-plugin-react-compiler"</span>,
           ReactCompilerConfig
          ]
        ],
    },
  })],
})
</code></pre>
<p>Here, you've added the <code>babel-plugin-react-compiler</code> to the configuration. The <code>ReactCompilerConfig</code> is required to provide any advanced configuration like if you want to provide any custom runtime module or any other configurations. In this case, it's an empty object without any advanced configurations.</p>
<p>That's it. You are done configuring the React compiler with your code base to utilize its power. From now on, the React compiler will look into every component and hook in your project to try and apply optimizations to it.</p>
<p>If you want to configure the React compiler with Next.js, Remix, Webpack, and so on, you can <a target="_blank" href="https://react.dev/learn/react-compiler#installation">follow this guide</a>.</p>
<h3 id="heading-optimized-react-app-with-react-compiler">Optimized React App with React Compiler</h3>
<p>Now you should have an optimized React app with the inclusion of the React compiler. So, let's run the same tests you did before. Again, change the value of the <code>heading</code> prop of the <code>ProductPage</code> component.</p>
<p>This time, you will not see the child components re-rendering. So the timestamp will not be updated either. But you will see the portion of the component where the data changed, as it will reflect the changes alone. Also, you won't have to use <code>memo</code>, <code>useMemo()</code>, or <code>useCallback()</code> in your code anymore.</p>
<p>You can see it working visually <a target="_blank" href="https://youtu.be/bdWUVp0TbTU?t=1326">from here</a>.</p>
<h2 id="heading-react-compiler-in-react-devtools">React Compiler in React DevTools</h2>
<p><a target="_blank" href="https://react.dev/learn/react-developer-tools">React DevTools</a> version 5.0+ has built-in support for the React compiler. You will see a badge with the text <code>Memo ✨</code> beside the components optimized by the React compiler. This is fantastic!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724303700810/2888b91c-bcec-4da2-88a6-840c51876d83.png" alt="React DevTools" class="image--center mx-auto" width="2412" height="1302" loading="lazy"></p>
<h2 id="heading-diving-deep-how-does-the-react-compiler-work">Diving Deep – How Does the React Compiler Work?</h2>
<p>Now that you've seen how the React compiler works on React 19 code, let's deep dive into understanding what's happening in the background. We will use the React <a target="_blank" href="https://playground.react.dev/">Compiler Playground</a> to explore the translated code and the optimization steps.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724740109843/a5047d83-4407-491f-8e11-6522c1381313.png" alt="React Compiler Playground" class="image--center mx-auto" width="2998" height="1394" loading="lazy"></p>
<p>We'll use the <code>Heading</code> component as an example. Copy and paste the following code inside the leftmost section of the playground:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Heading = <span class="hljs-function">(<span class="hljs-params">{ heading, totalProducts }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>
          {heading}({totalProducts}) - {Date.now()}
      <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
  )
}
</code></pre>
<p>You will see that some JavaScript code is generated immediately inside the <code>_JS</code> tab of the playground. The React compiler generates this JavaScript code as part of the compilation process. Let's go over it step-by-step:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">anonymous_0</span>(<span class="hljs-params">t0</span>) </span>{
  <span class="hljs-keyword">const</span> $ = _c(<span class="hljs-number">4</span>);
  <span class="hljs-keyword">const</span> { heading, totalProducts } = t0;
  <span class="hljs-keyword">let</span> t1;
  <span class="hljs-keyword">if</span> ($[<span class="hljs-number">0</span>] === <span class="hljs-built_in">Symbol</span>.for(<span class="hljs-string">"react.memo_cache_sentinel"</span>)) {
    t1 = <span class="hljs-built_in">Date</span>.now();
    $[<span class="hljs-number">0</span>] = t1;
  } <span class="hljs-keyword">else</span> {
    t1 = $[<span class="hljs-number">0</span>];
  }
  <span class="hljs-keyword">let</span> t2;
  <span class="hljs-keyword">if</span> ($[<span class="hljs-number">1</span>] !== heading || $[<span class="hljs-number">2</span>] !== totalProducts) {
    t2 = (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>
          {heading}({totalProducts}) - {t1}
        <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
    );
    $[<span class="hljs-number">1</span>] = heading;
    $[<span class="hljs-number">2</span>] = totalProducts;
    $[<span class="hljs-number">3</span>] = t2;
  } <span class="hljs-keyword">else</span> {
    t2 = $[<span class="hljs-number">3</span>];
  }
  <span class="hljs-keyword">return</span> t2;
}
</code></pre>
<p>The compiler uses a hook called <code>_c()</code> to create an array of items to cache. In the code above, an array of four elements has been created to cache four items.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> $ = _c(<span class="hljs-number">4</span>);
</code></pre>
<p>But, what are the things to cache?</p>
<ul>
<li><p>The component takes two props, <code>heading</code> and <code>totalProducts</code>. The compiler needs to cache them. So, it needs two elements in the array of cacheable items.</p>
</li>
<li><p>The <code>Date.now()</code> part in the header should be cached.</p>
</li>
<li><p>The JSX itself should be cached. There is no point in computing JSX unless either of the above changes.</p>
</li>
</ul>
<p>So there are a total of four items to cache.</p>
<p>The compiler creates memoization blocks using the <code>if-block</code>. The final return value from the compiler is the JSX which depends on three dependencies:</p>
<ul>
<li><p>The <code>Date.now()</code> value.</p>
</li>
<li><p>Two props, a <code>heading</code> and <code>totalProducts</code></p>
</li>
</ul>
<p>The output JSX needs re-computation when any of the above changes. This means that the compiler needs to create two memoization blocks for each of the above.</p>
<p>The first memoization block looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> ($[<span class="hljs-number">0</span>] === <span class="hljs-built_in">Symbol</span>.for(<span class="hljs-string">"react.memo_cache_sentinel"</span>)) {
    t1 = <span class="hljs-built_in">Date</span>.now();
    $[<span class="hljs-number">0</span>] = t1;
} <span class="hljs-keyword">else</span> {
    t1 = $[<span class="hljs-number">0</span>];
}
</code></pre>
<p>The if-block stores the value of the Date.now() into the first index of the cacheable array. It re-uses the same every time unless it is changed.</p>
<p>Similarly, in the second memoization block:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> ($[<span class="hljs-number">1</span>] !== heading || $[<span class="hljs-number">2</span>] !== totalProducts) {
    t2 = (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>
          {heading}({totalProducts}) - {t1}
        <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
    );
    $[<span class="hljs-number">1</span>] = heading;
    $[<span class="hljs-number">2</span>] = totalProducts;
    $[<span class="hljs-number">3</span>] = t2;
  } <span class="hljs-keyword">else</span> {
    t2 = $[<span class="hljs-number">3</span>];
  }
</code></pre>
<p>Here, the check is for the value changes for either <code>heading</code> or <code>totalProducts</code> props. If either of these changes, the JSX needs to be recomputed. All the values are then stored in the cacheable array. If there are no changes in the value, the previously computed JSX is returned from the cache.</p>
<p>You can now paste any other component source code into the left side and look into the generated JavaScript code to help you understand what's going on as we did above. This will help you to get a better grip on how the compiler performs the memoization techniques in the compilation process.</p>
<h2 id="heading-how-do-you-opt-in-and-out-of-the-react-compiler">How Do You Opt in and Out of the React Compiler?</h2>
<p>Once you've configured the React compiler the way we have done with our Vite project here, it's enabled for all the compilers and hooks of the project.</p>
<p>But in some cases, you may want to selectively opt-in for the React compiler. In that case, you can run the compiler in “opt-in” mode using the <code>compilationMode: "annotation"</code> option.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Specify the option in the ReactCompilerConfig</span>
<span class="hljs-keyword">const</span> ReactCompilerConfig = {
  <span class="hljs-attr">compilationMode</span>: <span class="hljs-string">"annotation"</span>,
};
</code></pre>
<p>Then annotate the components and hooks you want to opt-in for compilation with the <code>"use memo"</code> directive.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/ProductPage.jsx</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ProductPage</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-string">"use memo"</span>;
  <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>Note that there is a <code>"use no memo"</code> directive as well. There might be some rare cases where your component may not be working as expected after compilation, and you want to opt out of the compilation temporarily until the issue is identified and fixed. In that case, you can use this directive:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-string">"use no memo"</span>;
  <span class="hljs-comment">// ...</span>
}
</code></pre>
<h2 id="heading-can-we-use-the-react-compiler-with-react-18x">Can We Use the React Compiler with React 18.x?</h2>
<p>It is recommended to use the React compiler with React 19 as there are required compatibilities. If you can't upgrade your application to React 19, you'll need to have a custom implementation of the cache function. You can go over <a target="_blank" href="https://github.com/reactwg/react-compiler/discussions/6">this thread</a> describing the workaround.</p>
<h3 id="heading-repositories-to-look-into">Repositories to Look Into</h3>
<ul>
<li><p>All the source code used in this article is <a target="_blank" href="https://github.com/tapascript/react-compiler-lesson">in this repository</a>.</p>
</li>
<li><p>If you want to start coding with React 19 and its features, <a target="_blank" href="https://github.com/atapas/code-in-react-19">here is a template repository</a> configured with React 19 RC, Vite, and TailwindCSS. You may want to try it out.</p>
</li>
</ul>
<h2 id="heading-whats-next">What's Next?</h2>
<p>To learn further,</p>
<ul>
<li><p>Check out the official documentation of React Compiler <a target="_blank" href="https://react.dev/learn/react-compiler">from here</a>.</p>
</li>
<li><p>Check out the <a target="_blank" href="https://github.com/reactwg/react-compiler/discussions">discussions</a> in the Working Group.</p>
</li>
</ul>
<p>Up next, if you are willing to learn <code>React</code> and its ecosystem-like <code>Next.js</code> with both fundamental concepts and projects, I have great news for you: you can <a target="_blank" href="https://www.youtube.com/watch?v=VSB2h7mVhPg&amp;list=PLIJrr73KDmRwz_7QUvQ9Az82aDM9I8L_8">check out this playlist on my YouTube</a> channel with 22+ video tutorials and 12+ hours of engaging content so far, for free. I hope you like them as well.</p>
<p>That's all for now. Did you enjoy reading this article and have you learned something new? If so, I would love to know if the content was helpful.</p>
<ul>
<li><p>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</p>
</li>
<li><p><a target="_blank" href="https://twitter.com/tapasadhikary">Follow me on X (Twitter</a>) or <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</p>
</li>
<li><p>Check out and follow my Open Source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</p>
</li>
<li><p>I regularly publish meaningful posts on my <a target="_blank" href="https://blog.greenroots.info/">GreenRoots Blog</a>, you may find them helpful, too.</p>
</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself, and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Next.js App Performance With Lazy Loading ]]>
                </title>
                <description>
                    <![CDATA[ People don't like using slow applications. And the initial load time matters a lot for web applications and websites.  An application that takes more than 3 seconds to load is considered slow and may cause users to leave the application or website. N... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/next-js-performance-optimization/</link>
                <guid isPermaLink="false">66be00118c9c9099893ce790</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Fri, 19 Jul 2024 22:31:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/lazyloading-next.js.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>People don't like using slow applications. And the initial load time matters a lot for web applications and websites. </p>
<p>An application that takes more than 3 seconds to load is considered slow and may cause users to leave the application or website.</p>
<p><code>Next.js</code> is a React-based framework you can use to build scalable, performant, and faster web applications and websites. With the inclusion of <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-react-server-components/">React Server Components</a> in the Next.js app router release, developers have a new mental model for "thinking in a server components" way. It solves the problem with SEO, helps create <code>zero bundle size</code> React components, and the end result is faster loading of UI components.</p>
<p>But your application may not be always about the server components. You may need to use client components as well. Also, you may want to load them either as part of the application's initial load or on demand (say at the click of a button).</p>
<p>Loading a client component on the browser includes downloading the component code into the browser, downloading all the libraries and other components you had imported into that client component, and a few additional things that React takes care of for you to make sure your components are working. </p>
<p>Based on the user's internet connection and other network factors, the entire loading of the client component may take a while, which may keep your users from using the application more quickly.</p>
<p>This is where <code>Lazy Loading</code> techniques can come in handy. They can help save you from a monolithic loading of your client components on the browser. </p>
<p>In this article, we will discuss a couple of lazy loading techniques in Next.js for client component loading optimization. We will also talk about a few edge cases you should know to handle.</p>
<p>If you like to learn from video content as well, this article is also available as a video tutorial here: 🙂</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/gq9bBZru78Y" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>Before we get started, a couple of things for you:</p>
<ul>
<li>We will write a bunch of code to build an app to demonstrate the lazy loading techniques. You can find all the source code from this GitHub repository: <a target="_blank" href="https://github.com/tapascript/nextjs-lazy-load">https://github.com/tapascript/nextjs-lazy-load</a>. But I strongly suggest that you write the code yourself as we proceed and use the repository only as a reference.</li>
<li>You can also access the app deployed publicly <a target="_blank" href="https://nextjs-lazy-load.netlify.app/">on Netlify here</a>.</li>
</ul>
<p>Let's start 🚀. Oh yes, if you are Tom &amp; Jerry cartoon lover, you are going to enjoy this even more!</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-lazy-loading">What is Lazy Loading</a>?</li>
<li><a class="post-section-overview" href="#heading-lazy-loading-techniques-in-nextjs">Lazy Loading Techniques in Next.js</a></li>
<li><a class="post-section-overview" href="#heading-lazy-loading-with-dynamic-import-and-nextdynamic">Lazy Loading with dynamic import and next/dynamic</a></li>
<li><a class="post-section-overview" href="#heading-lazy-loading-with-reactlazy-and-suspense">Lazy Loading with React.lazy() and Suspense</a></li>
<li><a class="post-section-overview" href="#heading-how-to-lazy-load-the-named-exported-components">How to Lazy Load the Named Exported Components</a></li>
<li><a class="post-section-overview" href="#heading-lazy-loading-your-server-components-1">Lazy Loading Your Server Components</a></li>
<li><a class="post-section-overview" href="#heading-lazy-loading-your-server-components-1">Should We Lazy Load All Client Components in Next.js?</a></li>
<li><a class="post-section-overview" href="#heading-whats-next">What's Next?</a></li>
</ul>
<h2 id="heading-what-is-lazy-loading">What is Lazy Loading?</h2>
<p>In modern day web application development, we don't code all the logic in one JavaScript/TypeScript file, or all the styles into one mammoth CSS file. Rather, we split them at the source code level and create logical modules, business logic, presentational components, and style related files. This helps us organize our code better.</p>
<p>Then we use something called a bundler which kicks in at the build phase of the application development process. It creates bundles for our scripts and styles. Some of the famous bundlers are Webpack, Rollup, and Parcel, among others.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-43.png" alt="Image" width="600" height="400" loading="lazy">
<em>Bundler creating bundles from the source code</em></p>
<p>Now, as we have the bundles, if we try to load them on the browser all together, we will encounter some slowness. This is because the complete bundle needs to be loaded into the browser for the user interface to be functional. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-44.png" alt="Image" width="600" height="400" loading="lazy">
<em>Loading a huge bundle results in a poor loading experience</em></p>
<p>So, instead of waiting for the huge bundle to get loaded into the browser, modern web development libraries and tooling systems allow us to load the bundle in chunks. </p>
<p>We may want to load some of the chunks immediately, as users may need them sooner as the application loads. At the same time, we may want to wait to load certain parts of a web page until they're needed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/image-45.png" alt="Image" width="600" height="400" loading="lazy">
<em>Breaking into chunks and loading what is needed</em></p>
<p>This mechanism of waiting to load part of the pages or application, and loading them only when they are absolutely necessary, is called <code>Lazy Loading</code>. The concept of lazy loading is not React or Next.js-specific. It is a performance optimization technique that you can implement with various libraries and frameworks.</p>
<h2 id="heading-lazy-loading-techniques-in-nextjs">Lazy Loading Techniques in Next.js</h2>
<p>Lazy loading techniques in Next.js is used to reduce the amount of JavaScript needed by a route. This helps the initial load performance of the application be faster. We can defer the load of the client components and imported libraries until they are needed.</p>
<p>There are two ways we can implement lazy loading techniques in Next.js:</p>
<ul>
<li>Using dynamic imports with the help of the <code>next/dynamic</code> package.</li>
<li>Using a combination of <code>React.lazy()</code> and <code>Suspense</code>.</li>
</ul>
<p>Let's understand each of these techniques with code examples.</p>
<h2 id="heading-lazy-loading-with-dynamic-import-and-nextdynamic">Lazy Loading With <code>dynamic import</code> and <code>next/dynamic</code></h2>
<p><code>next/dynamic</code> is a combination of React.lazy() and Suspense from ReactJS. Using a dynamic import with the next/dynamic package is a preferred approach to achieve lazy loading in Next.js.</p>
<p>To demonstrate it, let's first create a Next.js app using the following command:</p>
<pre><code class="lang-bash">npx create-next-app@latest
</code></pre>
<p>You can start the app locally using the following command:</p>
<pre><code class="lang-bash"><span class="hljs-comment">## Using npm</span>
npm run dev

<span class="hljs-comment">## Using yarn</span>
yarn dev

<span class="hljs-comment">## Or use pnpm, bun, whatever you wish!</span>
</code></pre>
<p>Now create a folder called <code>components</code> under the <code>app/</code> directory. We will create all our components under the component folder. Now, create a folder called <code>tom</code> under the <code>app/components/</code>. Finally, create a React component called <code>tom.jsx</code> under the <code>app/components/tom/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// tom.jsx</span>

<span class="hljs-keyword">const</span> LazyTom = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl my-2"</span>&gt;</span>The Lazy Tom<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        Tom, named <span class="hljs-symbol">&amp;quot;</span>Jasper<span class="hljs-symbol">&amp;quot;</span> in his debut appearance, is a gray and white
        domestic shorthair cat 🐈. <span class="hljs-symbol">&amp;quot;</span>Tom<span class="hljs-symbol">&amp;quot;</span> is a generic name for a male cat. He is
        usually but not always, portrayed as living a comfortable, or even
        pampered life. Tom is no match for Jerry<span class="hljs-symbol">&amp;apos;</span>s wits.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        Although cats typically chase mice to eat them, it is quite rare for Tom
        to actually try to eat Jerry. He tries to hurt or compete with him just
        to taunt Jerry, even as revenge, or to obtain a reward from a human,
        including his owner(s)/master(s), for catching Jerry, or for generally
        doing his job well as a house cat. By the final <span class="hljs-symbol">&amp;quot;</span>fade-out<span class="hljs-symbol">&amp;quot;</span> of each
        cartoon, Jerry usually gets the best of Tom.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> LazyTom;
</code></pre>
<p>To explain the above code:</p>
<ul>
<li>We have created a ReactJS component called <code>LazyTom</code>.</li>
<li>It is a simple presentational component which has a heading and a couple of paragraphs talking about the cat, Tom, from the famous <code>Tom &amp; Jerry</code> cartoon.</li>
<li>At the end, we have <code>default</code> exported the component to import it elsewhere.</li>
</ul>
<p>Now, create another file called <code>tom-story.jsx</code> under the <code>app/components/tom/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// tom-story.jsx</span>

<span class="hljs-string">"use client"</span>;

<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">"next/dynamic"</span>;

<span class="hljs-keyword">const</span> LazyTom = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./tom"</span>), {
    <span class="hljs-attr">loading</span>: <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Loading Tom<span class="hljs-symbol">&amp;apos;</span>s Story...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">TomStory</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [shown, setShown] = useState(<span class="hljs-literal">false</span>);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-[300px]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>Demonstrating <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>dynamic<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-blue-600 text-white rounded p-1"</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setShown(!shown)}
            &gt;
                Load 🐈 Tom<span class="hljs-symbol">&amp;apos;</span>s Story
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

            {shown &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">LazyTom</span> /&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> TomStory;
</code></pre>
<p>The main magic of lazy loading with <code>dynamic</code> is happening in the above code:</p>
<ul>
<li>We have created a client component called <code>TomStory</code> using the <code>"use client"</code> directive.</li>
<li>First, we have imported the <code>useState</code> hook for managing a toggle state, and the <code>dynamic</code> function from the <code>next/dynamic</code> for the lazy loading of the component we created before.</li>
<li>The <code>dynamic</code> function takes a function as an argument that returns the imported component. You can also configure a custom loading message by providing an optional configuration object as argument to the dynamic function. </li>
<li>The <code>dynamic()</code> function returns the lazily loaded component instance – that is, <code>LazyTom</code> (could be any name). But this component is not loaded yet.</li>
<li>In the JSX, we have a toggle button that shows and hides the <code>LazyTom</code> component. Note that the component will be lazy loaded into the user browser at the first instance of a button click. After that, if you hide and show it again, the <code>LazyTom</code> component will not be reloaded until we hard refresh the browser or clear the browser cache.</li>
<li>Finally, we have default exported the <code>TomStory</code> component.</li>
</ul>
<p>Now we need to test it out. To do that, open the <code>page.js</code> file in the <code>app/</code> directory and replace the content with the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> TomStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/tom/tom-story"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-wrap justify-center "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TomStory</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>This is a simple ReactJS component that imports the <code>TomStory</code> component and uses it in its JSX. Now open your browser window. Open the browser's DevTools and open the <code>Network</code> tab. Make sure that the <code>All</code> filter is selected.</p>
<p>Now access the app on your browser using <code>http://localhost:3000</code>. You should see the button to load Tom's story. Also a bunch of resources will be listed on the <code>Network</code> tab. These are resources required in the initial load of the application and have been downloaded on your browser.</p>
<p>The <code>LazyTom</code> component from the <code>tom.jsx</code> has not been downloaded yet. This is because we haven't yet clicked on the <code>Load Tom's Story</code> button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.21.10-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>The button to lazy load Tom's story</em></p>
<p>Now, click on the button. You should see a loading message for a moment and then the component will be loaded with Tom's story. You can now see the <code>tom.jsx</code> component listed in the <code>Network</code> tab and also the component rendered on the page with the Tom's story.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.27.55-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Now Tom's story is lazily loaded</em></p>
<p>Now that you have experienced how the <code>dynamic</code> function from <code>next/dynamic</code> helps us load a component lazily, let's get started with the other technique using <code>React.lazy()</code> and <code>Suspense</code>.</p>
<h2 id="heading-lazy-loading-with-reactlazy-and-suspense">Lazy Loading with <code>React.lazy()</code> and <code>Suspense</code></h2>
<p>To demonstrate this technique, let's start with Jerry's story, my favourite character from the Tom &amp; Jerry cartoon. </p>
<p>First, we'll create a folder called <code>jerry</code> under the <code>app/components/</code> directory. Now, create a file called <code>jerry.jsx</code> under the <code>app/components/jerry/</code> with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// jerry.jsx</span>

<span class="hljs-keyword">const</span> LazyJerry = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col justify-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl my-2"</span>&gt;</span>The Lazy Jerry<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        Jerry 🐀, whose name is not explicitly mentioned in his debut appearance,
        is a small, brown house mouse who always lives in close proximity to
        Tom. Despite being very energetic, determined and much larger, Tom is no
        match for Jerry<span class="hljs-symbol">&amp;apos;</span>s wits. Jerry possesses surprising strength for his
        size, approximately the equivalent of Tom<span class="hljs-symbol">&amp;apos;</span>s, lifting items such as
        anvils with relative ease and withstanding considerable impacts.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        Although cats typically chase mice to eat them, it is quite rare for Tom
        to actually try to eat Jerry. He tries to hurt or compete with him just
        to taunt Jerry, even as revenge, or to obtain a reward from a human,
        including his owner(s)/master(s), for catching Jerry, or for generally
        doing his job well as a house cat. By the final <span class="hljs-symbol">&amp;quot;</span>fade-out<span class="hljs-symbol">&amp;quot;</span> of each
        cartoon, Jerry usually gets the best of Tom.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> LazyJerry;
</code></pre>
<p>The content of <code>jerry.jsx</code> is structurally similar to <code>tom.jsx</code>. Here we have posted Jerry's story, instead of Tom's, and default exported the component.</p>
<p>Like the last time, let's create a <code>jerry-story.jsx</code> file to showcase the lazy loading of Jerry's story. Create the file under the <code>app/components/jerry/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// jerry-story.jsx</span>

<span class="hljs-string">"use client"</span>;

<span class="hljs-keyword">import</span> React, { useState, Suspense } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> LazyJerry = React.lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./jerry'</span>));

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">JerryStory</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [shown, setShown] = useState(<span class="hljs-literal">false</span>);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-[300px]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span> Demonstrating <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>React.lazy()<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-pink-600 text-white rounded p-1"</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setShown(!shown)}
            &gt;
                Load 🐀 Jerry<span class="hljs-symbol">&amp;apos;</span>s Story
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

            {shown &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">h1</span>&gt;</span>Loading Jerry<span class="hljs-symbol">&amp;apos;</span>s Story<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>}&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">LazyJerry</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> JerryStory;
</code></pre>
<p>Here also we have a client component, and we will be using the <code>lazy()</code> method and <code>Suspense</code> from React, so we have imported them. Like the <code>dynamic()</code> function in the last technique, the <code>lazy()</code> function also takes a function as an argument that retrurns the lazily imported component. We have also provided the relative path to the component that we are trying to load.</p>
<p>Note that with <code>dynamic()</code> we had an opportunity to customize the loading message as part of the function itself. With <code>lazy()</code>, we will be doing that as part of the <code>Suspense</code> fallback. </p>
<p>Suspense uses a fallback when you wait for the data to load. If you would like to understand the Suspense and Error Boundary from ReactJS in-depth, you can <a target="_blank" href="https://www.youtube.com/watch?v=OpHbSHp8PcI">check out this video tutorial</a>. </p>
<p>Here, as our <code>LazyJerry</code> component is loading lazily, we have provided a fallback to show a loading message until the component code is download into the browser successfully and rendered.</p>
<pre><code class="lang-js">{shown &amp;&amp; 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">h1</span>&gt;</span>Loading Jerry<span class="hljs-symbol">&amp;apos;</span>s Story<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>}&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">LazyJerry</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span></span>
}
</code></pre>
<p>Also, as you can see, we are loading the component on the first button click. Here also, the component will not be reloaded every time we click on the button unless we refresh the browser or clear the browser cache.</p>
<p>Let's now test it by importing it into the <code>page.js</code> file and adding the component in its JSX.</p>
<pre><code class="lang-js"><span class="hljs-comment">// page.js</span>

<span class="hljs-keyword">import</span> TomStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/tom/tom-story"</span>;
<span class="hljs-keyword">import</span> JerryStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/jerry/jerry-story"</span>; 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-wrap justify-center "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TomStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">JerryStory</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now, you'll see another component appear on the user interface with a button to load Jerry's story. At this stage, you will not see the jerry.jsx component loaded into the browser.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.33.36-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>The button to lazy load Jerry's story</em></p>
<p>Now, click on the button. You will see that the component is loaded, and you can see it on the Network tab list. You should be able to read Jerry's story rendered as part of the lazily loaded component.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.37.30-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Jerry's story is lazily loaded</em></p>
<h2 id="heading-how-to-lazy-load-the-named-exported-components">How to Lazy Load the Named Exported Components</h2>
<p>So far, with both the techniques we have imported a component that was exported with the <code>default export</code> and then lazy loaded it. In JavaScript (and so in React), you can export and import modules in two different ways:</p>
<ul>
<li>With the <code>default</code> keyword. In this case, the exported module can be imported with any name. You would use this if you wanted to export only one functionality from a module.</li>
<li>Without the <code>default</code> keyword, this is called a <code>named export</code>. In this case, you have to maintain the same module name for the export and import. You also need to enclose the module name in the curly brackets ({...}) while importing. You would use this if you wanted to export multiple functionalities from a module.</li>
</ul>
<p>If you want to get into JavaScript modules and how they work in greater detail, I would suggest going through <a target="_blank" href="https://www.youtube.com/watch?v=KeBxopnhizw">this crash course</a> published on freeCodeCamp's YouTube channel.</p>
<p>To demonstrate the lazy loading of a <code>named export</code> component, let's create another simple presentational React component. This time we will use the angry but cute dog named <code>Spike</code> from the Tom &amp; Jerry cartoon.</p>
<p>Create a folder called <code>spike</code> under the <code>app/components/</code> directory. Now, create a file called <code>spike.jsx</code> under the <code>app/components/spike/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// spike.jsx</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> LazySpike = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl my-2"</span>&gt;</span>The Lazy Spike<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
        In his attempts to catch Jerry, Tom often has to deal with Spike 🦮, known
        as <span class="hljs-symbol">&amp;quot;</span>Killer<span class="hljs-symbol">&amp;quot;</span> and <span class="hljs-symbol">&amp;quot;</span>Butch<span class="hljs-symbol">&amp;quot;</span> in some shorts, an angry, vicious but easily
        duped bulldog who tries to attack Tom for bothering him or his son Tyke
        while trying to get Jerry. Originally, Spike was unnamed and mute, aside
        from howls and biting noises as well as attacking indiscriminately, not
        caring whether it was Tom or Jerry though usually attacking Tom.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>
      In
        later cartoons, Spike spoke often, using a voice and expressions,
        performed by Billy Bletcher and later Daws Butler, modeled after
        comedian Jimmy Durante. Spike<span class="hljs-symbol">&amp;apos;</span>s coat has altered throughout the years
        between gray and creamy tan. The addition of Spike<span class="hljs-symbol">&amp;apos;</span>s son Tyke in the
        late 1940s led to both a slight softening of Spike<span class="hljs-symbol">&amp;apos;</span>s character and a
        short-lived spin-off theatrical series called Spike and Tyke.
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Again, this component is structurally exactly same as the <code>tom.jsx</code> and <code>jerry.jsx</code> components we have seen before, but with two major differences:</p>
<ol>
<li>Here, we have exported the component without the default keyword, hence it is a <code>named export</code>.</li>
<li>We are talking about the dog, Spike.</li>
</ol>
<p>Now, we need to handle the lazy loading of a named exported component and it's going to be a bit different from the default exported component.</p>
<p>Create a file called <code>spike-story.jsx</code> under the <code>app/components/spike/</code> directory with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// spike-story.jsx</span>

<span class="hljs-string">"use client"</span>;

<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">"next/dynamic"</span>;

<span class="hljs-keyword">const</span> LazySpike = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./spike"</span>).then(<span class="hljs-function">(<span class="hljs-params">mod</span>) =&gt;</span> mod.LazySpike), {
    <span class="hljs-attr">loading</span>: <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Loading Spike<span class="hljs-symbol">&amp;apos;</span>s Story...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SpikeStory</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [shown, setShown] = useState(<span class="hljs-literal">false</span>);

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-[300px]"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-xl my-1"</span>&gt;</span>Demonstrating <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Named Export<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-slate-600 text-white rounded p-1"</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setShown(!shown)}
            &gt;
                Load 🦮 Spike<span class="hljs-symbol">&amp;apos;</span>s Story
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

            {shown &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">LazySpike</span> /&gt;</span>}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SpikeStory;
</code></pre>
<p>Like <code>tom-story</code>, we are using the dynamic import with the next/dynamic. But let's zoom into the following block from the above code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> LazySpike = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">"./spike"</span>).then(<span class="hljs-function">(<span class="hljs-params">mod</span>) =&gt;</span> mod.LazySpike), {
    <span class="hljs-attr">loading</span>: <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Loading Spike<span class="hljs-symbol">&amp;apos;</span>s Story...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
});
</code></pre>
<p>The changes you will notice here are that we are resolving the promise explicitly from the <code>import("./spike")</code> function using the the <code>.then()</code> handler function. We get the module first, and then pick the exported component by its actual name – that is <code>LazySpike</code> in this case. The rest of the things remain the same as before as in the <code>tom-story</code>.</p>
<p>Now to test it out, again import the component into the <code>page.js</code> file, and use it in the JSX  like the last two times.</p>
<pre><code class="lang-js"><span class="hljs-comment">// page.js</span>

<span class="hljs-keyword">import</span> TomStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/tom/tom-story"</span>;
<span class="hljs-keyword">import</span> JerryStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/jerry/jerry-story"</span>;
<span class="hljs-keyword">import</span> SpikeStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/spike/spike-story"</span>; 

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-wrap justify-center "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TomStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">JerryStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SpikeStory</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>There you go – you should see the new component rendered on the browser with a button to load Spike's story from the <code>spike.jsx</code> file which is not loaded yet.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-9.59.55-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>The button to lazy load Spike's story</em></p>
<p>Clicking on the button will load the file into the browser and render the component to show you Spike's story.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-10.02.01-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Spike's story is lazily loaded</em></p>
<p>Below you can see all three components demonstrating three different techniques and uses cases side-by-side. You can test them together. The image below is showcasing lazy loading of two components in parallel where another component was already lazily loaded.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-10.14.21-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Lazily loading multiple components in parallel</em></p>
<p>Here is another case where all three components were lazy loaded, on demand with the respective button clicks. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/07/Screenshot-2024-07-17-at-10.05.35-AM-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>All the stories lazy loaded</em></p>
<h2 id="heading-lazy-loading-your-server-components">Lazy Loading Your Server Components</h2>
<p>We spoke about the lazy loading techniques of client components. Can we use the same on server components as well? Well, you can but you don't have to, as server components are already <code>code split</code> and the loading aspect is already been taken care of by Next.js. You are not going to get any kind of error if you are trying to do so, but it would be unnecessary. </p>
<p>In case, you are dynamically importing a server component that has one or more client components as children, those client components will be lazy loaded. But there won't be any impact on the (parent) server component itself.</p>
<p>Here is an example of a server component that has two client components as children:</p>
<pre><code class="lang-js"><span class="hljs-comment">// server-comp.jsx</span>

<span class="hljs-keyword">import</span> ComponentA <span class="hljs-keyword">from</span> <span class="hljs-string">"./a-client-comp"</span>;
<span class="hljs-keyword">import</span> ComponentB <span class="hljs-keyword">from</span> <span class="hljs-string">"./b-client-comp"</span>;

<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-keyword">const</span> AServerComp = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-[300px]"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ComponentA</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ComponentB</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AServerComp
</code></pre>
<p>Now, we are dynamically importing the server component into the <code>page.js</code> file and using it in its JSX. The child client components of the dynamically imported server component will be lazy loaded, but not the server component itself.</p>
<pre><code class="lang-js"><span class="hljs-comment">// page.js</span>

<span class="hljs-keyword">import</span> dynamic <span class="hljs-keyword">from</span> <span class="hljs-string">"next/dynamic"</span>;

<span class="hljs-keyword">import</span> TomStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/tom/tom-story"</span>;
<span class="hljs-keyword">import</span> JerryStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/jerry/jerry-story"</span>;
<span class="hljs-keyword">import</span> SpikeStory <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/spike/spike-story"</span>;

<span class="hljs-keyword">const</span> AServerComp = dynamic(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./components/server-comps/server-comp'</span>), {
  <span class="hljs-attr">loading</span>: <span class="hljs-function">() =&gt;</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Loading Through Server Component...<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
})


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-wrap justify-center "</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">TomStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">JerryStory</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">SpikeStory</span> /&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">AServerComp</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h2 id="heading-should-we-lazy-load-all-client-components-in-nextjs">Should We Lazy Load All Client Components in Next.js?</h2>
<p>I had this question when I first started learning about lazy loading. Now that I have gained more experience with this technique, here is my perspective:</p>
<p>You don't have to lazy load all client components. Optimzation is great, but over optimization can have adverse effects. You need to identify where these optimizations are required. </p>
<ul>
<li>Do you have client components that are really bulky? </li>
<li>Are you unnecessarily putting so many things into one component that you should break it down and refactor? </li>
<li>Do you import heavy libraries into your client components? </li>
<li>Have you opted for tree-shaking? </li>
<li>Can you mark bulky client components per route and is it fine not to load some or all of them at the initial load of the page for that route?</li>
</ul>
<p>As you see, these are a bunch of meaningful questions to ask before you step into optimizing things. Once you have answers, and decide you need lazy loading, then you can implement the techniques you learned from this article.</p>
<h2 id="heading-whats-next">What's Next?</h2>
<p>That's all for now. Did you enjoy reading this article and have you learned something new? If so, I would love to know if the content was helpful. I have my social handles provided below.</p>
<p>Up next, if you are willing to learn <code>Next.js</code> and its ecosystem like <code>Next-Auth(V5)</code> with both fundamental concepts and projects, I have a great news for you: you can <a target="_blank" href="https://www.youtube.com/watch?v=VSB2h7mVhPg&amp;list=PLIJrr73KDmRwz_7QUvQ9Az82aDM9I8L_8">check out this playlist on my YouTube</a> channel with 20+ video tutorials and 11+ hours of engaging content so far, for free. I hope you like them as well.</p>
<p>Let's connect.</p>
<ul>
<li>Subscribe to my <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">YouTube Channel</a>.</li>
<li><a target="_blank" href="https://twitter.com/tapasadhikary">Follow me on X (Twitter</a>) or <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of up-skilling tips.</li>
<li>Check out and follow my Open Source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</li>
<li>I regularly publish meaningful posts on my <a target="_blank" href="https://blog.greenroots.info/">GreenRoots Blog</a>, you may find them helpful, too.</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself, and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Should You Learn TypeScript? Pros and Cons of TS Explained ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll explore the question: is TypeScript worth learning? Before we try finding the answer together, let me tell you why I'm suddenly asking this. I come from a Java background where writing code demands that you be type-aware. This ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/should-you-learn-typescript/</link>
                <guid isPermaLink="false">66be001bcab9472fe774186f</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Fri, 10 May 2024 14:50:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/typescript-worth-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll explore the question: is TypeScript worth learning? Before we try finding the answer together, let me tell you why I'm suddenly asking this.</p>
<p>I come from a Java background where writing code demands that you be type-aware. This means that if you are declaring a string, you would have to write its type as <code>String</code> explicitly, like this:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Declaring a String in Java</span>

String greeting = <span class="hljs-string">"Is TypeScript Worth Learning?"</span>
</code></pre>
<p>After developing software products with Java for 8 long years, when I shifted to <code>JavaScript</code>, the developer inside me was thrilled – so much so that it felt like, "Oh man! I finally got a fresh breath of air”. </p>
<p>I didn't have to worry about types and declaring them beforehand. I seemed to be writing less code, and the world was suddenly a paradise of freedom for me to build, test, and ship.</p>
<p>Another enjoyable 4 years passed with JavaScript and I grew up to become a senior developer. Then I got my formal introduction to <code>TypeScript</code>. </p>
<p>So here is my opportunity to tell you what I think, and whether TypeScript is worth learning. I am going to share the experience I've earned over the years. If you agree/disagree/want to know more, my socials are mentioned at the bottom of this article. I would love to connect and discuss. Keep reading. </p>
<p>If you would also like to check out the video version of this article, here it is: 😊</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/whGzNBqdNS0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-typescript">What is TypeScript?</a>            </li>
<li><a class="post-section-overview" href="#heading-getting-started-with-typescript-the-challenges">Getting Started with TypeScript – The Challenges</a></li>
<li><a class="post-section-overview" href="#heading-learning-more-about-typescript-the-benefits">Learning More About TypeScript – The Benefits</a></li>
<li><a class="post-section-overview" href="#heading-baby-steps-to-start-coding-in-typescript">Baby Steps to Start Coding in TypeScript</a></li>
<li><a class="post-section-overview" href="#heading-so-whats-the-verdict-is-typescript-worth-it-or-not">So What's The Verdict: Is TypeScript Worth It or Not?</a></li>
<li><a class="post-section-overview" href="#heading-before-we-end">Before We End...</a></li>
</ul>
<h2 id="heading-what-is-typescript">What is TypeScript?</h2>
<p><code>TypeScript</code> is JavaScript at its core with additional syntax for types. Traditionally, JavaScript is a loosely typed language. Its flexibility in allowing developers to use (or misuse) random type assignments may lead to unwanted bugs in their applications. </p>
<p>That's where TypeScript comes in handy as a strongly typed programming language. It helps safe-guard devs from breaking applications at runtime by helping with type checks at code compilation time. You can learn more about TypeScript and its Type Safety from <a target="_blank" href="https://www.typescriptlang.org/">the official TypeScript site</a>.</p>
<p>TypeScript helps JavaScript developers catch errors early in their code editor. The experience of being aware of the possible errors as you code can help you and your team trust the final output the code will produce. </p>
<p>If you know JavaScript, you do not have to learn any additional programming fundamentals to code in TypeScript. You just need to be aware of its type system and related syntax to apply them on your JavaScript code.</p>
<p>Personally, TypeScript has changed the way I used to code and ship my products. But it was not a cake walk to get into the mindset of using TypeScript by sacrificing all the flexibility you get with JavaScript. I had my own challenges and ways to overcome them.</p>
<p>This article is for every developer who comes across those challenges when they start coding in TypeScript. And it's meant to help you with the mindset you'll need to appreciate TypeScript's strictness, and how to identify biased (and false) information related to TypeScript to make the right choice for your projects.</p>
<p>Remember, TypeScript is not for everyone or every occasion. But it'll be easier for you to make the choice if you are aware of  its qualities, where it fits in, and where it doesn't. I hope you this article helps you start understanding TypeScript's benefits and limitations, and that you enjoy the process of selecting or rejecting TypeScript for your upcoming projects. </p>
<h2 id="heading-getting-started-with-typescript-the-challenges">Getting Started with TypeScript – The Challenges</h2>
<p>To be honest, starting with TypeScript was a shock for me, and it proved to be a bit of a nightmare. This was primarily because of the following challenges:</p>
<h3 id="heading-project-setup-and-tools-needed">Project Setup and Tools Needed</h3>
<p>It was not as simple as opening up the browser DevTool's Console tab, and starting to write code to see the output. This works great with JavaScript, and I – like many other beginners – had started gaining confidence coding in JavaScript by writing the code in the browser directly. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-12.png" alt="Image" width="600" height="400" loading="lazy">
<em>Writing JavaScript in the browser DevTool's console tab</em></p>
<p>With TypeScript, though, the browser doesn't understand its syntax. And you might be left wondering...what's next?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-13.png" alt="Image" width="600" height="400" loading="lazy">
<em>You can't run the TypeScript program the same way - you'll get an error</em></p>
<p>You may start realizing that you need additional tools and build systems to print a “Hello World” on the console.</p>
<h3 id="heading-the-typescript-compiler">The TypeScript Compiler</h3>
<p>So, is there a compiler, too? Also, are you saying that the TypeScript Compiler (tsc) compiles the TypeScript code to create equivalent JavaScript code which we will run eventually? That’s weird. Then why not code in JavaScript directly? This thought baffles many developers starting with TypeScript.</p>
<h3 id="heading-the-one-and-only-tsconfigjson-file">The “One and Only” <code>tsconfig.json</code> File</h3>
<p>TypeScript projects need explicit configurations to work in an environment that you define. You provide the configurations using the <code>tsconfig.json</code> file. It allows you to configure the output file path, type strictness, how to handle TypeScript related-features like <code>any</code>, and how you want TypeScript to treat <code>null</code>, <code>undefined</code>, and so on.</p>
<p>The good news is, it works great once you've configure things correctly. But the bad news is, as a newbie, you may be clueless about an error like the one you see below in the <code>tsconfig.json</code> file, even when you haven't touched the file at all.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-14.png" alt="Image" width="600" height="400" loading="lazy">
<em>The curious case of the tsconfig file.</em></p>
<h3 id="heading-the-sense-of-slowing-you-down">The Sense of Slowing You Down</h3>
<p>As a beginner to TypeScript (especially when you have already spent a good amount of time working with JavaScript), you may feel like you're being slowed down. The feeling comes from the need to always be defining your types. </p>
<p>That's when you start thinking:</p>
<ul>
<li>I'm writing extra code.</li>
<li>Extra code means extra hours of work.</li>
<li>That's extra brain power and maintenance.</li>
<li>Am I overcomplicating some of the simple patterns of JavaScript?</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/clock.gif" alt="Image" width="600" height="400" loading="lazy">
<em>After a few days...</em></p>
<h2 id="heading-learning-more-about-typescript-the-benefits">Learning More About TypeScript – The Benefits</h2>
<p>If you haven't given up yet, and you're still in exploration mode, your perspective of TypeScript may start changing. Here are some of the benefits of coding in TypeScript:</p>
<h3 id="heading-type-safety">Type Safety</h3>
<p>TypeScript is a superset of JavaScript. It has everything that JavaScript has, plus it ensures <code>Type Safety</code>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-15.png" alt="Image" width="600" height="400" loading="lazy">
<em>TypeScript as a superset of JavaScript</em></p>
<p>Type safety is a mechanism to ensure you are using the right types of values in your code. It helps safeguard your applications from breaking something at runtime (in production when your users are using the application). TypeScript also ensures type safety at compile time, much before you push any code changes to other developers or to your users.</p>
<p>Here is an example of some type-safe code in TypeScript. The function <code>sumOfTwo</code> accepts two parameters of <code>number</code> type and returns a value that is also of <code>number</code> type. </p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sumOfTwo</span>(<span class="hljs-params">a: number, b: number</span>): <span class="hljs-title">number</span> </span>{
    <span class="hljs-keyword">return</span> a + b;
}
</code></pre>
<p>If the caller of the function doesn't adhere to the types defined, the code will not compile and produces compilation errors.</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(sumOfTwo(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>)); <span class="hljs-comment">// 3</span>
<span class="hljs-built_in">console</span>.log(sumOfTwo(<span class="hljs-number">1</span>,<span class="hljs-number">-1</span>)); <span class="hljs-comment">// 0</span>

<span class="hljs-built_in">console</span>.log(sumOfTwo(<span class="hljs-string">"tapas"</span>, <span class="hljs-number">1</span>)); <span class="hljs-comment">// TypeError</span>
</code></pre>
<p>This behaviour of TypeScript safe-guards your code so it doesn't fail in production from any type-related errors.</p>
<h3 id="heading-easier-learning-curve">Easier Learning Curve</h3>
<p>Type Safety is fine. How about the learning curve? If you know JavaScript already, your learning curve for TypeScript will be smaller. </p>
<p>If you do not know JavaScript, you can consider starting with TypeScript straightway, as learning JavaScript is equally challenging.</p>
<h3 id="heading-the-tooling-problem">The Tooling Problem</h3>
<p>Fortunately, there are ways to handle the initial tooling and build system problem we discussed before. Developers around the world have been using TypeScript for a while now and there are existing resources to get the help you need and set everything up. </p>
<p>If you have prior knowledge of Node and the JavaScript ecosystem, it may take half a day to set things up. If you do not have either Node or JavaScript or both, it may take a couple days max.</p>
<p>I have been through a similar phase, and now I have my own environment to use for all my TypeScript projects. You can <a target="_blank" href="https://github.com/tapascript/ts-gyan">check it out on my GitHub</a> and feel free to start using it. If you want to create something similar and customize it to create your own, <a target="_blank" href="https://www.youtube.com/watch?v=P3unJiZxfkI">this guide</a> will help you with that.</p>
<p>Also, the best part is, all this setup is a one-time job. You do it once, and you can replicate or reuse it for all your future projects. </p>
<p>You will also understand the power of VS Code IntelliSense while coding in TypeScript. It prompts you with code completion to make your coding experience even better.</p>
<h3 id="heading-how-about-the-tsconfig-thingy">How about the tsconfig thingy?</h3>
<p>Undoubtedly, you'll need some time to learn about the configuration properties in the <code>tsconfig.json</code> file and what they do. But the positive thing is you do not need to know them all. </p>
<p>When you are getting started, just make sure you know what is minimally needed for your project and learn about those things. Rest assured that you can learn other things as and when you need them.</p>
<h2 id="heading-baby-steps-to-start-coding-in-typescript">Baby Steps to Start Coding in TypeScript</h2>
<p>After the initial struggle with tooling, building, and configuration, you may be itching to write your first line of TypeScript code (assuming you haven't started blaming TypeScript for your lack of productivity yet!). </p>
<p>Let's look at some scenario-based comparisons between the flexible world of JavaScript and the strict world of TypeScript.</p>
<h3 id="heading-javascript-vs-typescript-examples">JavaScript vs TypeScript Examples</h3>
<p>A simple sum of two numbers in JavaScript would look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sumOfTwo</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-built_in">console</span>.log(sumOfTwo(<span class="hljs-number">1</span>,<span class="hljs-number">2</span>)); <span class="hljs-comment">// 3</span>
<span class="hljs-built_in">console</span>.log(sumOfTwo(<span class="hljs-number">1</span>,<span class="hljs-number">-1</span>)); <span class="hljs-comment">// 0</span>
</code></pre>
<p>But doing the same thing with TypeScript would require an extra bit of code to tell the TypeScript compiler about the type of the parameters and the return type:</p>
<pre><code class="lang-tsx">function sumOfTwo(a: number, b: number): number {
  return a + b;
}

console.log(sumOfTwo(1,2)); // 3
console.log(sumOfTwo(1,-1)); // 0
</code></pre>
<p>Hmm! That seems to be more work than necessary. But it's really more helpful than you can imagine. It guards your code against considering unacceptable inputs instead of what the more "flexible" JavaScript would allow:</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sumOfTwo</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}

<span class="hljs-built_in">console</span>.log(sumOfTwo(<span class="hljs-number">1</span>, <span class="hljs-literal">true</span>)); <span class="hljs-comment">// The output is 2</span>
<span class="hljs-built_in">console</span>.log(sumOfTwo(<span class="hljs-number">1</span>, [])); <span class="hljs-comment">// Believe or not, it will result 1</span>
</code></pre>
<p>Trying out the above code in TypeScript wouuld result in compilation errors. If you are running the TypeScript compiler in watch mode (with the command <code>tsc -w</code>), you can catch these errors while writing the code itself!</p>
<pre><code class="lang-tsx">function sumOfTwo(a: number, b: number): number {
  return a + b;
}

console.log(sumOfTwo(1, true)); // Error
console.log(sumOfTwo(1, [])); // Error
</code></pre>
<p>That's not all. Let’s take another example. Consider an employee array with the details of a few employees in your JavaScript code:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Employee Object</span>

<span class="hljs-keyword">const</span> employees = [
    {
        <span class="hljs-attr">id</span>: <span class="hljs-string">'01'</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">'Alex'</span>,
        <span class="hljs-attr">age</span>: <span class="hljs-number">23</span>,
        <span class="hljs-attr">married</span>: <span class="hljs-literal">false</span>
    },
    {
        <span class="hljs-attr">id</span>: <span class="hljs-string">'02'</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">'Bob'</span>,
        <span class="hljs-attr">age</span>: <span class="hljs-number">3</span>,
        <span class="hljs-attr">married</span>: <span class="hljs-literal">false</span>
    },
    {
        <span class="hljs-attr">id</span>: <span class="hljs-string">'03'</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">'Clara'</span>,
        <span class="hljs-attr">age</span>: <span class="hljs-number">28</span>,
        <span class="hljs-attr">married</span>: <span class="hljs-literal">true</span>
    }
];
</code></pre>
<p>Now, let's say you want to filter out the married employees. </p>
<pre><code class="lang-js"><span class="hljs-comment">// Filter the married employees</span>

employees.filter(<span class="hljs-function"><span class="hljs-params">emp</span> =&gt;</span> emp.married) <span class="hljs-comment">// Clara</span>
</code></pre>
<p>It works great! But imagine if some of the employee data is incorrect somewhere. What if you are getting the employee object as an API response where the <code>married</code> property value of the employee <code>Bob</code> is set to <code>3</code> by mistake!</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">const</span> employees = [
    {
        <span class="hljs-attr">id</span>: <span class="hljs-string">'01'</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">'Alex'</span>,
        <span class="hljs-attr">age</span>: <span class="hljs-number">23</span>,
        <span class="hljs-attr">married</span>: <span class="hljs-literal">false</span>
    },
    {
        <span class="hljs-attr">id</span>: <span class="hljs-string">'02'</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">'Bob'</span>,
        <span class="hljs-attr">age</span>: <span class="hljs-number">3</span>,
        <span class="hljs-attr">married</span>: <span class="hljs-number">3</span>
    },
    {
        <span class="hljs-attr">id</span>: <span class="hljs-string">'03'</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">'Clara'</span>,
        <span class="hljs-attr">age</span>: <span class="hljs-number">28</span>,
        <span class="hljs-attr">married</span>: <span class="hljs-literal">true</span>
    }
];
</code></pre>
<p>Now, your same logic of filtering the married employees would result in saying both Bob and Clara are the married employees – but Bob may not be married at all.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Filter the married employees</span>

employees.filter(<span class="hljs-function"><span class="hljs-params">emp</span> =&gt;</span> emp.married) <span class="hljs-comment">// Bob and Clara</span>
</code></pre>
<p>Hold on! You can still safe-guard the above situation with some lines of extra logic in your JavaScript code. How about you check the type of the value of each employee's <code>married</code> property in the array and throw an error if it's not a <code>boolean</code>?</p>
<pre><code class="lang-jsx">employees.filter(<span class="hljs-function">(<span class="hljs-params">employee</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> employee.married  === <span class="hljs-string">'boolean'</span>) {
      <span class="hljs-keyword">return</span> employee.married &amp;&amp; employee;
  } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"The employee.married type is not of boolean type."</span>)
  }
});
</code></pre>
<p>This fixes the problem. But hang on, isn’t that:</p>
<ul>
<li>Extra lines of code you have written to safe guard your code from failing?</li>
<li>Extra hours of work?</li>
<li>Extra brain power and maintenance? What if similar value mistakes happen in other properties of the employee object? Would you keep adding conditions in the filter callback?</li>
<li>Overcomplicating some of the simple patterns of JavaScript?</li>
</ul>
<p>A better and safer situation is to use TypeScript and type safe each of the properties of the employee object either by defining a <a target="_blank" href="https://youtu.be/VE5SOoP2Y74?list=PLIJrr73KDmRy_ufvq5m_4KwnxUdx9Sq3d">type or using interfaces</a>.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">type</span> Employee = {
    id: <span class="hljs-built_in">string</span>,
    name: <span class="hljs-built_in">string</span>,
    age: <span class="hljs-built_in">number</span>,
    married: <span class="hljs-built_in">boolean</span>
}
</code></pre>
<h2 id="heading-so-whats-the-verdict-is-typescript-worth-it-or-not">So What's The Verdict: Is TypeScript Worth It or Not?</h2>
<p>If you are coming to this section following the previous sections of this article, then the following points will make sense to you:</p>
<ul>
<li>You may not like TypeScript just by looking into it, what it promises, and the code written with it. You need to spend some time with TypeScript by writing code, and building projects with it.</li>
<li>The complexity of tooling, builds, and configurations shouldn't stand in your way. There are many resources to help you figure these things out. As we discussed before, these are solved problems, and you don't need to reinvent the wheel.</li>
<li>For JavaScript developers, it can hard to accept TypeScript without a deeper understanding of JavaScript itself. But the more you learn about it, the more I think you'll see that TypeScript indeed has an edge that'll help safeguard you and your team from type issues.</li>
</ul>
<p>Now the question is – is it worth it?</p>
<p>Absolutely yes! Especially so if:</p>
<ul>
<li>Your project is beyond a simple app like a TODO app.</li>
<li>You want to catch type errors and mistakes at compile time while writing your code instead of in production.</li>
<li>The project is being developed by a team of JavaScript developers.</li>
<li>You want to debug your code efficiently.</li>
<li>You are looking for a common data contract interface between client and server for data exchange.</li>
<li>Last but not least, if you don't want to miss out on the job opportunities that come with knowing TypeScript. If you know JavaScript basics, getting started with TypeScript will not be hard if you get proper guidance.</li>
</ul>
<h2 id="heading-before-we-end">Before We End...</h2>
<p>I want to end this article with a quote: </p>
<blockquote>
<p>“Learning is an experience. Everything else is just information.” – Albert Einstein.</p>
</blockquote>
<p>So it's up to you to decide if something is worth learning.</p>
<p>It should depend on why, rather than what, you want to learn. You will have limitations with how many things you can learn in your lifetime…so learn wisely.</p>
<p>This is also why I started my TypeScript playlist practically to make sure you don't come in with certain assumptions. I want you to learn TypeScript first so you can be a confident decision-maker when technology choices come. </p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=whGzNBqdNS0&amp;list=PLIJrr73KDmRy_ufvq5m_4KwnxUdx9Sq3d">Here is the link to my TypeScript playlist</a> if you want to check it out. The playlist will break down each of the configurations, concepts, and project building in a beginner-friendly way to help you learn TypeScript rapidly.</p>
<p>That's all for now. I hope you found this article informative and insightful. I am an educator on my YouTube channel, <code>tapaScript</code>. Please <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">SUBSCRIBE</a> to the channel if you want to learn JavaScript, TypeScript, ReactJS, Next.js, Node.js, Git, and all about Web Development in a fundamental way.</p>
<p>Let's connect.</p>
<ul>
<li><a target="_blank" href="https://twitter.com/tapasadhikary">Follow me on X (Twitter</a>) or <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of Career Tips.</li>
<li>Find all my public speaking talks <a target="_blank" href="https://www.tapasadhikary.com/talks">here</a>.</li>
<li>Check out and follow my Open Source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</li>
<li>I regularly publish meaningful posts on my <a target="_blank" href="https://blog.greenroots.info/">GreenRoots Blog</a>, you may find them helpful, too.</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself, and stay happy.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create an Inventory List with React useReducer, Axios, and JSON Server ]]>
                </title>
                <description>
                    <![CDATA[ When it comes to web development, it's hard to ignore React.js. It has been one of the leading user interface libraries for a decade, and it supports a lot of popular frameworks like Next.js in the background. If you are a React developer, you likely... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-an-inventory-list-with-react-usereducer-axios-and-json-server/</link>
                <guid isPermaLink="false">66bdffd3422f318982ba47c0</guid>
                
                    <category>
                        <![CDATA[ axios ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hooks ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tapas Adhikary ]]>
                </dc:creator>
                <pubDate>Thu, 07 Mar 2024 15:33:49 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/inventory-list.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When it comes to web development, it's hard to ignore React.js. It has been one of the leading user interface libraries for a decade, and it supports a lot of popular frameworks like Next.js in the background.</p>
<p>If you are a React developer, you likely appreciate its component-based architecture, uni-directional data binding, huge community support, and the React team's passion for bringing features in front of developers.</p>
<p>If you are just getting started with React or a beginner at it, that's great – there's a complete <a target="_blank" href="https://www.freecodecamp.org/news/react-fundamentals-for-beginners/">React.js roadmap published here</a> on the freeCodeCamp you can check out. And I think you'll find the library a lot easier to learn if you have a solid grip on basic JavaScript foundations.</p>
<p>Irrespective of where you stand with React, the real fun is in building things with it, don't you agree? So I thought of building a simple <code>inventory list</code> to explain a few powerful concepts like complex state management with useReducer. </p>
<p>And while we're doing that, we'll also create a mock API server using <code>JSON Server</code>, we'll use <code>axios</code> to call the API, and finally we'll use the <code>useReducer</code> hook to manage state.</p>
<p>Sounds interesting? Let's do it. If you would also like to check out the video version of this project, here it is: 😊</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/jKyAEj0EvAA" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-project-setup-with-react-and-tailwindcss">Project Setup with React and TailwindCSS</a></li>
<li><a class="post-section-overview" href="#heading-how-to-setup-a-server-with-json-server">How to Setup a Server with JSON Server</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-and-use-axios">How to Set Up and Use Axios</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-usereducer-hook-from-react">How to Use the useReducer Hook from React</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-actions">How to Create Actions</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-an-inventory-reducer">How to Create an Inventory Reducer</a></li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-inventory-list-component">How to Build the Inventory List Component</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-axios-to-fetch-data-and-dispatch-it-to-the-reducer">How to Use Axios to Fetch Data and Dispatch it to the Reducer</a></li>
<li><a class="post-section-overview" href="#heading-lets-complete-the-jsx-part">Let's Complete the JSX Part</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-inventory-list-in-the-app-component">How to Use the Inventory List in the App Component</a></li>
<li><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></li>
</ul>
<h2 id="heading-project-setup-with-react-and-tailwindcss">Project Setup with React and TailwindCSS</h2>
<p>Before we do anything else, let's get the project set up. Also, you can follow along with the <a target="_blank" href="https://github.com/atapas/youtube/tree/main/react/27-inventory-useReducer-jsonserver-axios">source code</a> as you read through.</p>
<p>To build this app, we will use React with <code>Vite</code> and <code>TailwindCSS</code>. You can set up these tools by following a few steps from the <a target="_blank" href="https://vitejs.dev/guide/">Vite</a> and <a target="_blank" href="https://tailwindcss.com/docs/guides/vite">TailwindCSS</a> documentation.</p>
<p>But, why not use something that provides everything built together? This will save you time for future React projects as you can use the same infrastructure to create a React projects every time.</p>
<p>Head over to this <a target="_blank" href="https://github.com/atapas/vite-tailwind-react">repository</a> and click on the <code>Use this template</code> button as indicated in the image below. It will help you create a brand new repository out of a template repository with Vite, React, and TailwindCSS configured.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-12-at-5.25.29-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create a React Project Repository with TailwindCSS and Vite from an Existing Template</em></p>
<p>Now provide a suitable name to your repository (let's call it <code>inventory-list</code> in this article) along with a description. You may chose to keep the repository private if you wish to, otherwise go ahead and create the repository by clicking on the button at the bottom.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/02/Screenshot-2024-02-12-at-5.30.34-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Provide the Details of the New Repository</em></p>
<p>That's it. You have a repository with all the basic ingredients to get started. Now, go to the command prompt/terminal and clone the newly created repository:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> &lt;YOUR NEWLY CREATED REPOSITORY URL&gt;
</code></pre>
<p>Change directories to the project directory and install the project dependencies using the following commands:</p>
<pre><code class="lang-bash"><span class="hljs-comment">## Change to the project directory</span>
<span class="hljs-built_in">cd</span> inventory-list

<span class="hljs-comment">## Install dependencies</span>

<span class="hljs-comment">## Using NPM</span>
npm install

<span class="hljs-comment">## Using Yarn</span>
yarn install

<span class="hljs-comment">## Using PNPM</span>
pnpm install
</code></pre>
<p>After the dependencies are installed successfully, execute the following command to run the project on a local server:</p>
<pre><code class="lang-bash"><span class="hljs-comment">## Run the project locally</span>

<span class="hljs-comment">## Using NPM</span>
npm run dev

<span class="hljs-comment">## Using Yarn</span>
yarn dev

<span class="hljs-comment">## Using PNPM</span>
pnpm dev
</code></pre>
<p>Now the project should be running locally and should be accessible on the default URL, <code>http://localhost:5173</code>. You can access the URL on yor browser and import the project source code into your favourite code editor (I use VS Code). We are all set to start the coding.</p>
<h2 id="heading-how-to-setup-a-server-with-json-server">How to Setup a Server with JSON Server</h2>
<p><code>JSON Server</code> is the go-to option when you want to work with fake/mock APIs to serve data of your choice. It is easy to set up and customize to your use case. </p>
<p>Let's set up the JSON Server for our project. The first thing is to install it.</p>
<p>Open a terminal at the root of the project folder and type the following command to install JSON Server:</p>
<pre><code class="lang-shell">## Using NPM
npm install json-server

## Using Yarn
yarn add json-server

## Using PNPM
pnpm install json-server
</code></pre>
<p>JSON Server uses JSON files as the data sources to perform HTTP operations like GET/POST/PUT/PATCH/DELETE. Create a <code>server/database</code> directory under the <code>src/</code> directory. Now create a file called <code>data.json</code> under the <code>src/server/database/</code> with the following content:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"edibles"</span>: [
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-number">1</span>,
      <span class="hljs-attr">"picture"</span>: <span class="hljs-string">"🍌"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Banana"</span>,
      <span class="hljs-attr">"price"</span>: <span class="hljs-number">32</span>,
      <span class="hljs-attr">"quantity"</span>: <span class="hljs-number">200</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"fruits"</span>
    },
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-number">2</span>,
      <span class="hljs-attr">"picture"</span>: <span class="hljs-string">"🍓"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Strawberry"</span>,
      <span class="hljs-attr">"price"</span>: <span class="hljs-number">52</span>,
      <span class="hljs-attr">"quantity"</span>: <span class="hljs-number">100</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"fruits"</span>
    },
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-number">3</span>,
      <span class="hljs-attr">"picture"</span>: <span class="hljs-string">"🍗"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Checken"</span>,
      <span class="hljs-attr">"price"</span>: <span class="hljs-number">110</span>,
      <span class="hljs-attr">"quantity"</span>: <span class="hljs-number">190</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"foods"</span>,
      <span class="hljs-attr">"sub-type"</span>: <span class="hljs-string">"Non-Veg"</span>
    },
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-number">4</span>,
      <span class="hljs-attr">"picture"</span>: <span class="hljs-string">"🥬"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Lettuce"</span>,
      <span class="hljs-attr">"price"</span>: <span class="hljs-number">12</span>,
      <span class="hljs-attr">"quantity"</span>: <span class="hljs-number">50</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Vegetables"</span>
    },
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-number">5</span>,
      <span class="hljs-attr">"picture"</span>: <span class="hljs-string">"🍅"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Tomato"</span>,
      <span class="hljs-attr">"price"</span>: <span class="hljs-number">31</span>,
      <span class="hljs-attr">"quantity"</span>: <span class="hljs-number">157</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Vegetables"</span>
    },
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-number">6</span>,
      <span class="hljs-attr">"picture"</span>: <span class="hljs-string">"🥩"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Mutton"</span>,
      <span class="hljs-attr">"price"</span>: <span class="hljs-number">325</span>,
      <span class="hljs-attr">"quantity"</span>: <span class="hljs-number">90</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Non-Veg"</span>
    },
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-number">7</span>,
      <span class="hljs-attr">"picture"</span>: <span class="hljs-string">"🥕"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Carrot"</span>,
      <span class="hljs-attr">"price"</span>: <span class="hljs-number">42</span>,
      <span class="hljs-attr">"quantity"</span>: <span class="hljs-number">190</span>,
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Vegetables"</span>
    }
  ]
}
</code></pre>
<p>The <code>data.json</code> file contains an array of edible items. Each of the items in the array has properties like picture, name, price, quantity, and type to show in the inventory list.</p>
<p>The last thing left is to add a script into the <code>package.json</code> file so that we can start the JSON Server easily every time. Open the package.json file and add this line inside the <code>scripts</code> object like this:</p>
<pre><code class="lang-json"><span class="hljs-string">"start-server"</span>: <span class="hljs-string">"json-server --watch ./src/server/database/data.json"</span>
</code></pre>
<p>Next, go to the terminal and use the following command to start the JSON Server to serve the API:</p>
<pre><code class="lang-shell">## Using NPM
npm run start-server

## Using Yarn
yarn start-server

## Using PNPM
pnpm run start-server
</code></pre>
<p>You should see a message like this in your terminal:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/Screenshot-2024-03-07-at-8.46.32-AM-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Output</em></p>
<p>It indicates that the JSON Server is running locally on <code>localhost:3000</code> and there is an API endpoint called <code>edibles</code> serves the data. Now you can access the URL <code>http://localhost:3000/edibles</code> from your browser to see the data (fetched by a GET method call):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/image-32.png" alt="Image" width="600" height="400" loading="lazy">
<em>The API Output</em></p>
<p>Great! Now we have the <code>/edibles</code> API endpoint ready to consume into the React component.</p>
<h2 id="heading-how-to-set-up-and-use-axios">How to Set Up and Use Axios</h2>
<p><code>Axios</code> is an HTTP client that helps us make promise-based asynchronous calls from the browser and Node.js environment. It has a number of <a target="_blank" href="https://www.npmjs.com/package/axios#features">useful features</a> that make it one of the most used libraries for asynchronous request-response.</p>
<p>Note that we could have used the <code>fetch Web API</code> from JavaScript instead of <code>Axios</code> in this project. The only reason for using Axios here is to introduce it progressively. In the future articles, you'll learn its usages in handling JWT tokens from a React application. Stay tuned!</p>
<p>Open the terminal at the root of the project folder and use the following command to install Axios:</p>
<pre><code class="lang-shell">## Using NPM
npm install axios

## Using Yarn
yarn add axios

## Using PNPM
pnpm install axios
</code></pre>
<p>That's it. We will use Axios in a bit after laying out the basic components needed for the inventory list.</p>
<h2 id="heading-how-to-use-the-usereducer-hook-from-react">How to Use the useReducer Hook from React</h2>
<p>React is a user interface library that supports component-based architecture at the core. A component is a single entity that's supposed to perform one task well. Multiple components come together to compose the final user interface.</p>
<p>Often, a component will have its own private data. We call these the <code>states</code> of a component. The value of a state drives the behaviour and appearance of a component. When state changes, the component re-renders to keep itself up-to-date with the latest state value.</p>
<p>The traditional way of handling state in React is with the <code>useState</code> hook. It works great as long as your state changes are trivial. As the state change logic becomes more complex and if you need to manage multiple scenarios around it, <code>useState</code> may make things clumsy. This is where you should think about using the <code>useReducer</code> hook.</p>
<p><code>useReducer</code> is a standard hook from the React library. It accepts two primary parameters:</p>
<ul>
<li><code>initState</code>: the initial state value</li>
<li><code>reducer</code>: a JavaScript function that holds the state change logic based on an action (or trigger).</li>
</ul>
<p>The hook returns the following:</p>
<ul>
<li>A <code>state</code>: the current state value.</li>
<li>A <code>dispatch</code> function: a function that tells the respective reducer what to do next, and what data to act on.</li>
</ul>
<p>The image below explains each of the entities of the <code>useReducer</code> hook. If you want to learn about this hook in a greater depth, feel free to <a target="_blank" href="https://www.youtube.com/watch?v=PMyPyT8N4m8">check this out</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/image-27.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Anatomy of the useReducer Hook</em></p>
<h2 id="heading-how-to-create-actions">How to Create Actions</h2>
<p>The reducer function is the heart of the useReducer hook. It performs all the necessary logic to keep your application state updated and valid. </p>
<p>But how would the reducer function be aware of its task? Who would tell the reducer function what to do and what kind of data to work on? Here comes <code>actions</code>, an object that contains all the details for the reducer.</p>
<p>We define actions with types that indicate the stages a state change will occur in the reducer function. The same action object may also carry the application data(at times we call it payload) to pass to the reducer function when a component performs a dispatch.</p>
<p>We will now get started by creating some actions. We will define the types here. As our reducer needs to manage the inventory state on a data fetch, data fetch success, and data fetch error, we'll be defining actions for each of those.</p>
<p>Create a directory called <code>actions/</code> under the <code>src/</code> directory. Now create a file called <code>index.js</code> under the <code>src/actions/</code> directory with the following content:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> FETCH_ACTIONS = {
  <span class="hljs-attr">PROGRESS</span>: <span class="hljs-string">'progress'</span>,
  <span class="hljs-attr">SUCCESS</span>: <span class="hljs-string">'success'</span>,
  <span class="hljs-attr">ERROR</span>: <span class="hljs-string">'error'</span>,
}

<span class="hljs-keyword">export</span> { FETCH_ACTIONS };
</code></pre>
<p>We have defined three actions, PROGRESS, SUCCESS, and ERROR. Next, let's create the reducer.</p>
<h2 id="heading-how-to-create-an-inventory-reducer">How to Create an Inventory Reducer</h2>
<p>We need a reducer where we will keep all the state change logic. The same reducer will be passed to the <code>useReducer</code> hook later to get the current state value and dispatch the function to the component.</p>
<p>Create a directory called <code>reducers/</code> under the <code>src/</code>. Now, create a file called <code>inventoryReducers.js</code> under the <code>src/reducers/</code> directory.</p>
<p>Our reducer will need the actions because it has to work on state changes based on the actions. So, let's import the actions into the <code>inventoryReducers.js</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { FETCH_ACTIONS } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>
</code></pre>
<p>You can define an initial state in the reducer file. The <code>useReducer</code> hook needs a reducer and an initial state to give us the current state value, remember? Let's define an initial state.</p>
<p>We need to show a list of inventory items after getting a successful API response. While we are fetching the list of items by making an API call, we need to manage a loading data state. </p>
<p>In case there is any problem in fetching data, we need to report the error using the error state. So we can create an initial state with all these values as object properties.</p>
<p>Now, create an initialState variable with the following state object value assigned to it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">items</span>: [],
  <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,
}
</code></pre>
<p>Next, let's create the reducer function. Create a function called <code>inventoryReducer</code> with the following code snippet:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> inventoryReducer = <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {

  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> FETCH_ACTIONS.PROGRESS: {
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">loading</span>: <span class="hljs-literal">true</span>,
      }
    }

    <span class="hljs-keyword">case</span> FETCH_ACTIONS.SUCCESS: {
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">items</span>: action.data,
      }
    }

    <span class="hljs-keyword">case</span> FETCH_ACTIONS.ERROR: {
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">error</span>: action.error,
      }
    }

    <span class="hljs-attr">default</span>: {
      <span class="hljs-keyword">return</span> state;
    }      
  }

}
</code></pre>
<p>Let's understand the above code snippet. The <code>inventoryReducer</code> function takes two arguments, <code>state</code> and <code>action</code>. The reducer function works on the state based on the action type. For example,</p>
<ul>
<li>When it is a <code>PROGRESS</code> action, we want the <code>loading</code> value to be true.</li>
<li>For a <code>SUCCESS</code> action, we want to populate the <code>items</code> with the data received from the API response along with making the <code>loading</code> value as false.</li>
<li>For an <code>ERROR</code> action, we'll provide a value to the <code>error</code> property of the state.</li>
</ul>
<p>In any of the cases above, we do not mutate the state directly. Rather, we create a clone (a new reference of it using the <code>...</code> operator) of the state and then update its properties accordingly. Finally, we return the updated state for each of the actions. If the passed actions do not match any of the given types, we return back the state as it is.</p>
<p>Last, export the <code>inventoryReducer</code> function and the <code>initialState</code> object:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> {inventoryReducer, initialState};
</code></pre>
<p>Here is the complete code from the <code>inventoryReducers.js</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { FETCH_ACTIONS } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>

<span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">items</span>: [],
  <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">error</span>: <span class="hljs-literal">null</span>,
}

<span class="hljs-keyword">const</span> inventoryReducer = <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {

  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> FETCH_ACTIONS.PROGRESS: {
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">loading</span>: <span class="hljs-literal">true</span>,
      }
    }

    <span class="hljs-keyword">case</span> FETCH_ACTIONS.SUCCESS: {
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">items</span>: action.data,
      }
    }

    <span class="hljs-keyword">case</span> FETCH_ACTIONS.ERROR: {
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">loading</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">error</span>: action.error,
      }
    }

    <span class="hljs-attr">default</span>: {
      <span class="hljs-keyword">return</span> state;
    } 
  }

}

<span class="hljs-keyword">export</span> {inventoryReducer, initialState};
</code></pre>
<h2 id="heading-how-to-build-the-inventory-list-component">How to Build the Inventory List Component</h2>
<p>We will now create the inventory list component where we will use the reducer we created above.</p>
<p>Create a directory called <code>components/</code> under the <code>src/</code> directory. Now, create a file called <code>InventoryList.jsx</code> under the <code>stc/components/</code> directory.</p>
<p>First import the required things like:</p>
<ul>
<li>The <code>useReducer</code> hook where we will use the inventory reducer.</li>
<li>The <code>useEffect</code> hook to handle the async call with Axios.</li>
<li>The <code>inventory reducer</code> and the <code>initial state</code> we created a few minutes back.</li>
<li>The <code>actions</code>, as we need them to dispatch.</li>
<li>The <code>axios</code> for making async calls.</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useReducer, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> { inventoryReducer, initialState } <span class="hljs-keyword">from</span> <span class="hljs-string">"../reducers/inventoryReducer"</span>;

<span class="hljs-keyword">import</span> { FETCH_ACTIONS } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>;

<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;
</code></pre>
<p>Now, create a function to define the component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> InventoryList = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">const</span> [state, dispatch] = useReducer(inventoryReducer, initialState);

  <span class="hljs-keyword">const</span> { items, loading, error} = state;

  <span class="hljs-keyword">return</span>(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-2/5"</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Here,</p>
<ul>
<li>We have used the <code>useReducer</code> hook. We passed the <code>inventoryReducer</code> and the <code>initialState</code> to it as arguments to get the current <code>state</code> value and the <code>dispatch</code> function.</li>
<li>As we know the state object has the <code>items</code>, <code>loading</code>, and <code>error</code> as properties, we <code>destructure</code> them into our component. We will use them shortly.</li>
<li>The component returns an empty div that we will change as we proceed.</li>
</ul>
<p>Finally export the component as a default export like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> InventoryList;
</code></pre>
<h2 id="heading-how-to-use-axios-to-fetch-data-and-dispatch-it-to-the-reducer">How to Use Axios to Fetch Data and Dispatch it to the Reducer</h2>
<p>It's data fetching time! Data fetching by making an asynchronous call is a side effect you need to handle in your component. Copy and paste the <code>useEffect</code> code block inside the <code>InventoryList</code> function. </p>
<pre><code class="lang-js"><span class="hljs-comment">// -- The code above as it is</span>

<span class="hljs-keyword">const</span> InventoryList = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-comment">// --- The code above as it is</span>


  useEffect(<span class="hljs-function">() =&gt;</span> {
    dispatch({<span class="hljs-attr">type</span>: FETCH_ACTIONS.PROGRESS});

    <span class="hljs-keyword">const</span> getItems = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span>{
        <span class="hljs-keyword">let</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">"http://localhost:3000/edibles"</span>);
        <span class="hljs-keyword">if</span> (response.status === <span class="hljs-number">200</span>) {
          dispatch({<span class="hljs-attr">type</span>: FETCH_ACTIONS.SUCCESS, <span class="hljs-attr">data</span>: response.data});
        }
      } <span class="hljs-keyword">catch</span>(err){
        <span class="hljs-built_in">console</span>.error(err);
        dispatch({<span class="hljs-attr">type</span>: FETCH_ACTIONS.ERROR, <span class="hljs-attr">error</span>: err.message})
      }
    }

    getItems();

  }, []);

  <span class="hljs-comment">// --- The JSX return statement below as it is</span>
</code></pre>
<p>Let's understand the code flow:</p>
<ul>
<li>At the start of the <code>useEffect</code> callback, we dispatched a <code>PROGRESS</code> action. It invokes the reducer function with progress action type to turn the <code>loading</code> property value to true. We can use the loading property value in the JSX later to show a loading indicator.</li>
<li>Then we use Axios to make an asynchronous call using the API URL. On receiving the response, we check if it's a success, and in that case we dispatch a <code>SUCCESS</code> action along with the <code>items</code> data(remember, payload?) from response. This time the dispatcher will invoke the reducer with the success action to change the <code>items</code> and <code>loading</code> properties accordingly.</li>
<li>If there is an error, we dispatch an error action with the error message to update the state with the error information in the reducer.</li>
</ul>
<p>Each time we dispatch an action and update the state, we also get back the latest state value into our component. It's time to use the state value in the JSX to render the inventory item list.</p>
<h2 id="heading-lets-complete-the-jsx-part">Let's Complete the JSX Part</h2>
<p>The JSX part is fairly simple:</p>
<pre><code class="lang-js">
<span class="hljs-comment">// -- The code above as it is</span>

<span class="hljs-keyword">const</span> InventoryList = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-comment">// -- The code above as it is</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-2/5"</span>&gt;</span>
      {
        loading ? (
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        ) : error ? (
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{error}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        ) : (
          <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl my-4"</span>&gt;</span>Item List<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            {
              items.map((item) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col p-2 my-2 bg-gray-200 border rounded-md"</span> 
                  <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'my-2 text-xl'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span> {' '} {item.picture} of type <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{item.type}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
                    {' '} costs <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{item.price}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span> INR/KG.
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mb-2 text-lg'</span>&gt;</span>
                    Available in Stock: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{item.quantity}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              ))
            }

          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        )
      }

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> InventoryList;
</code></pre>
<p>Here's what's going on in the code:</p>
<ul>
<li>We show a <code>loading...</code> message if the loading property of the state is true. </li>
<li>We show the error message in case there's an error.</li>
<li>In neither of the cases, we iterate through the inventory items using the map function. Each of the items in the <code>items</code> array has information like picture, name, price, and more. We show this information in a meaningful way.</li>
</ul>
<p>Here is the complete code of the <code>InventoryList</code> component:</p>
<pre><code class="lang-js">
<span class="hljs-keyword">import</span> { useReducer, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { inventoryReducer, initialState } <span class="hljs-keyword">from</span> <span class="hljs-string">"../reducers/inventoryReducer"</span>;
<span class="hljs-keyword">import</span> { FETCH_ACTIONS } <span class="hljs-keyword">from</span> <span class="hljs-string">"../actions"</span>;

<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-keyword">const</span> InventoryList = <span class="hljs-function">() =&gt;</span> {

  <span class="hljs-keyword">const</span> [state, dispatch] = useReducer(inventoryReducer, initialState);

  <span class="hljs-keyword">const</span> { items, loading, error} = state;

  <span class="hljs-built_in">console</span>.log(items, loading, error);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    dispatch({<span class="hljs-attr">type</span>: FETCH_ACTIONS.PROGRESS});

    <span class="hljs-keyword">const</span> getItems = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span>{
        <span class="hljs-keyword">let</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">"http://localhost:3000/edibles"</span>);
        <span class="hljs-keyword">if</span> (response.status === <span class="hljs-number">200</span>) {
          dispatch({<span class="hljs-attr">type</span>: FETCH_ACTIONS.SUCCESS, <span class="hljs-attr">data</span>: response.data});
        }
      } <span class="hljs-keyword">catch</span>(err){
        <span class="hljs-built_in">console</span>.error(err);
        dispatch({<span class="hljs-attr">type</span>: FETCH_ACTIONS.ERROR, <span class="hljs-attr">error</span>: err.message})
      }
    }

    getItems();

  }, []);


  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col m-8 w-2/5"</span>&gt;</span>
      {
        loading ? (
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        ) : error ? (
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{error}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        ) : (
          <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl my-4"</span>&gt;</span>Item List<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            {
              items.map((item) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col p-2 my-2 bg-gray-200 border rounded-md"</span> 
                  <span class="hljs-attr">key</span>=<span class="hljs-string">{item.id}</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'my-2 text-xl'</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{item.name}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span> {' '} {item.picture} of type <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{item.type}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
                    {' '} costs <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{item.price}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span> INR/KG.
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'mb-2 text-lg'</span>&gt;</span>
                    Available in Stock: <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>{item.quantity}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              ))
            }

          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        )
      }

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> InventoryList
</code></pre>
<h2 id="heading-how-to-use-the-inventory-list-in-the-app-component">How to Use the Inventory List in the App Component</h2>
<p>Now we have to let the <code>App</code> component know about the <code>InventoryList</code> component so that we can render it. Open the <code>App.jsx</code> file and replace its content with the following code snippet:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> InventoryList <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/InventoryList"</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">InventoryList</span> /&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre>
<p>That's it. Make sure your application server is running. Now, access the app on your browser using the following URL <a target="_blank" href="http://localhost:5173/"><code>http://localhost:5173/</code></a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/03/image-28.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Final Output - Inventory List</em></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>I hope you enjoyed building this project and learning more about React. <a target="_blank" href="https://github.com/atapas/youtube/tree/main/react/27-inventory-useReducer-jsonserver-axios">Here is the source code</a> on my GitHub. Please feel free to extend the project by adding features like:</p>
<ul>
<li>Adding an item to the inventory</li>
<li>Editing an item from the inventory</li>
<li>Deleting an item from the inventory</li>
</ul>
<p>Hint: You need to create actions for each of these and enhance the reducer function to write state update logic to support these features. I hope you give it a try and if you do so, let me know (my contacts are mentioned below). </p>
<p>That's all for now. I also publish meaningful posts on my <a target="_blank" href="https://blog.greenroots.info/">GreenRoots Blog</a>, and I think you'll find them helpful, too.</p>
<p>Let's connect.</p>
<ul>
<li>I am an educator on my YouTube channel, <code>tapaScript</code>. Please <a target="_blank" href="https://www.youtube.com/tapasadhikary?sub_confirmation=1">SUBSCRIBE</a> to the channel if you want to learn JavaScript, ReactJS, Next.js, Node.js, Git, and all about Web Development fundamentally.</li>
<li><a target="_blank" href="https://twitter.com/tapasadhikary">Follow me on X (Twitter</a>) or <a target="_blank" href="https://www.linkedin.com/in/tapasadhikary/">LinkedIn</a> if you don't want to miss the daily dose of Web Development and Programming Tips.</li>
<li>Find all my public speaking talks <a target="_blank" href="https://www.tapasadhikary.com/talks">here</a>.</li>
<li>Check out and follow my Open Source work on <a target="_blank" href="https://github.com/atapas">GitHub</a>.</li>
</ul>
<p>See you soon with my next article. Until then, please take care of yourself, and stay happy.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
