<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alifa Ara Heya</title>
    <description>The latest articles on DEV Community by Alifa Ara Heya (@alifa_ara_heya).</description>
    <link>https://dev.to/alifa_ara_heya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2028039%2Ffe0f7323-916a-4721-b423-dc511bfb30fe.png</url>
      <title>DEV Community: Alifa Ara Heya</title>
      <link>https://dev.to/alifa_ara_heya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alifa_ara_heya"/>
    <language>en</language>
    <item>
      <title>Understanding Default Operator (`||`) vs Nullish Coalescing Operator (`??`) in JavaScript</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Thu, 02 Oct 2025 21:55:45 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/understanding-default-operator-vs-nullish-coalescing-operator-in-javascript-48je</link>
      <guid>https://dev.to/alifa_ara_heya/understanding-default-operator-vs-nullish-coalescing-operator-in-javascript-48je</guid>
      <description>&lt;p&gt;When working with JavaScript, it’s common to provide &lt;strong&gt;default values&lt;/strong&gt; in case a variable is missing or undefined. Two popular ways are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using the &lt;strong&gt;logical OR operator (&lt;code&gt;||&lt;/code&gt;)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Using the &lt;strong&gt;nullish coalescing operator (&lt;code&gt;??&lt;/code&gt;)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While they may look similar, they behave differently — and knowing the difference will save you from subtle bugs.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 The Default Operator (&lt;code&gt;||&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;||&lt;/code&gt; operator returns the right-hand side value if the left-hand side is &lt;em&gt;falsy&lt;/em&gt;.&lt;br&gt;
In JavaScript, the following are considered &lt;strong&gt;falsy&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;""&lt;/code&gt; (empty string)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;false&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NaN&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Guest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Guest"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, even though &lt;code&gt;userName&lt;/code&gt; is an empty string (which might be valid input), it is treated as falsy. So &lt;code&gt;"Guest"&lt;/code&gt; is used instead.&lt;/p&gt;

&lt;p&gt;Another case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 10 (oops, we actually wanted 0)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔹 The Nullish Coalescing Operator (&lt;code&gt;??&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;??&lt;/code&gt; operator only considers &lt;strong&gt;&lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;&lt;/strong&gt; as missing values.&lt;br&gt;
Other falsy values like &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;, or &lt;code&gt;""&lt;/code&gt; are preserved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Guest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "" (empty string is valid, not replaced)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0 ✅ (correct, because 0 is a valid number)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ✅ Advantage of &lt;code&gt;??&lt;/code&gt; over &lt;code&gt;||&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The key benefit of &lt;code&gt;??&lt;/code&gt; is that it &lt;strong&gt;does not mistakenly override valid falsy values&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With &lt;code&gt;||&lt;/code&gt;, values like &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;""&lt;/code&gt;, or &lt;code&gt;false&lt;/code&gt; are treated as missing.&lt;/li&gt;
&lt;li&gt;With &lt;code&gt;??&lt;/code&gt;, only &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; are treated as missing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes &lt;code&gt;??&lt;/code&gt; especially useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0&lt;/code&gt; is a valid count (e.g., items in a cart)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;""&lt;/code&gt; is a valid string (e.g., optional text fields)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;false&lt;/code&gt; is a valid boolean flag (e.g., user preferences)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔹 Quick Comparison Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operator&lt;/th&gt;
&lt;th&gt;Treats as “missing”&lt;/th&gt;
&lt;th&gt;Preserves 0 / "" / false?&lt;/th&gt;
&lt;th&gt;Example Result&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;`&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;`&lt;/td&gt;
&lt;td&gt;All falsy values (&lt;code&gt;0&lt;/code&gt;, &lt;code&gt;""&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;`0 \&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{% raw %}&lt;code&gt;??&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Only &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0 ?? 5 → 0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🌍 Real-World Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. API Response Defaults
&lt;/h3&gt;

&lt;p&gt;When working with APIs, some fields may be missing (&lt;code&gt;null&lt;/code&gt;/&lt;code&gt;undefined&lt;/code&gt;) but others might be valid even if falsy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;itemCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;itemCount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 0 (valid number, not replaced!)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you used &lt;code&gt;||&lt;/code&gt;, this would incorrectly give &lt;code&gt;10&lt;/code&gt; instead of &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Config Settings with Boolean Flags
&lt;/h3&gt;

&lt;p&gt;Sometimes &lt;code&gt;false&lt;/code&gt; is a &lt;strong&gt;deliberate setting&lt;/strong&gt;, not a missing value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;darkMode&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false (respects the user setting)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;||&lt;/code&gt; here would incorrectly turn it into &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. User Input Handling
&lt;/h3&gt;

&lt;p&gt;A user might leave a text field empty intentionally. With &lt;code&gt;??&lt;/code&gt;, you can respect that choice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Default text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "" (user chose empty string, not replaced)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;||&lt;/code&gt;, this would turn into &lt;code&gt;"Default text"&lt;/code&gt; unexpectedly.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;||&lt;/code&gt; when you want to fall back on &lt;em&gt;any falsy&lt;/em&gt; value.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;??&lt;/code&gt; when you want to &lt;strong&gt;preserve valid falsy values&lt;/strong&gt; and only handle &lt;code&gt;null&lt;/code&gt;/&lt;code&gt;undefined&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In modern JavaScript, &lt;code&gt;??&lt;/code&gt; is often the safer choice for handling defaults, especially with APIs, configs, and user input.&lt;/p&gt;




&lt;p&gt;👉 Next time you’re about to write &lt;code&gt;||&lt;/code&gt; for defaults, ask yourself: &lt;em&gt;Do I really want to override &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;""&lt;/code&gt;, or &lt;code&gt;false&lt;/code&gt;?&lt;/em&gt;&lt;br&gt;
If not — reach for &lt;code&gt;??&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>HTTP Requests in React(fetch vs Axios and Tanstack Query)</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Sun, 17 Aug 2025 16:45:24 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/http-requests-in-react-10jk</link>
      <guid>https://dev.to/alifa_ara_heya/http-requests-in-react-10jk</guid>
      <description>&lt;p&gt;As a web developer, understanding how to communicate with a server is fundamental. In React, you'll frequently use HTTP requests to Create, Read, Update, and Delete (CRUD) data. This note will walk you through three common approaches: the built-in fetch API, the popular library Axios, and the powerful state management tool TanStack Query. We'll start with the foundational fetch API, explore the improvements offered by Axios, and then see how a library like TanStack Query can manage the entire data-fetching lifecycle for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Native fetch API
&lt;/h2&gt;

&lt;p&gt;The fetch API is a built-in browser function that provides a clean, promise-based interface for making network requests. While it's the native solution and requires no external dependencies, its raw nature means you're responsible for handling a lot of the boilerplate yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boilerplate for a GET Request with fetch
&lt;/h3&gt;

&lt;p&gt;The standard approach involves using the &lt;code&gt;useEffect&lt;/code&gt; and &lt;code&gt;useState&lt;/code&gt; hooks to manage the request lifecycle. To properly handle asynchronous data, we need state variables to track the data itself, the loading status of the request, and any potential errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;FetchExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP error! status: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// The empty dependency array ensures this runs once on mount&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;FetchExample&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ata330cb1cd0jx3i161.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ata330cb1cd0jx3i161.png" alt="The Foundation: The Native  raw `fetch` endraw  API" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A Deeper Look at fetch's Promise Chain and Error Handling
&lt;/h3&gt;

&lt;p&gt;One of the most important distinctions of the fetch API is how it handles errors. A fetch promise will only reject if a network error occurs (e.g., no internet connection). It will not reject for common HTTP errors like 404 Not Found or 500 Server Error. Instead, the promise will resolve successfully, and you must manually check the &lt;code&gt;response.ok&lt;/code&gt; property or the &lt;code&gt;response.status&lt;/code&gt; code to handle these cases. This is why the &lt;code&gt;if (!response.ok)&lt;/code&gt; check is a crucial part of the boilerplate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full CRUD Operations with fetch
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;POST (Create):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New Item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Item created:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error creating item:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;PUT (Update):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/items/123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Updated Item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Item updated:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error updating item:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DELETE (Delete):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/items/123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Deletion failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Item deleted successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error deleting item:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the manual handling of success and error cases for each request can lead to repetitive code, especially in a large application.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Axios: The Easier Alternative
&lt;/h2&gt;

&lt;p&gt;Axios is a popular, promise-based HTTP client for both the browser and Node.js. It's often favored for its simplicity and built-in features that the native fetch API lacks. It provides a cleaner, more intuitive API, reducing the amount of boilerplate needed for common tasks.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  fetch vs. Axios
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;fetch (Native)&lt;/th&gt;
&lt;th&gt;Axios (Library)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parsing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual &lt;code&gt;response.json()&lt;/code&gt; call&lt;/td&gt;
&lt;td&gt;Automatic JSON data parsing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Doesn't reject on HTTP errors (e.g., 404, 500)&lt;/td&gt;
&lt;td&gt;Rejects promises on HTTP errors, simplifying try/catch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Headers, body, etc. are configured manually&lt;/td&gt;
&lt;td&gt;Instance-level configuration (base URL, headers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interceptors&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No built-in interceptors&lt;/td&gt;
&lt;td&gt;Interceptors to handle requests/responses globally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Request &amp;amp; Response Data&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Response object and request body handling can be cumbersome&lt;/td&gt;
&lt;td&gt;Data is available directly in the &lt;code&gt;response.data&lt;/code&gt; property&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Boilerplate for a GET Request with Axios
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AxiosExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

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

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;AxiosExample&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Going Deeper with Axios: Interceptors and Configuration
&lt;/h3&gt;

&lt;p&gt;One of Axios's most powerful features is its use of interceptors. These are functions that let you inspect and modify every HTTP request and response before they are handled by &lt;code&gt;then()&lt;/code&gt; or &lt;code&gt;catch()&lt;/code&gt;. They are perfect for common tasks like adding an authentication token to every request or logging errors globally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: A Request Interceptor for Authentication&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// services/api.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Add a request interceptor&lt;/span&gt;
&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authToken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, every time you use this &lt;code&gt;api&lt;/code&gt; instance, it will automatically check for an &lt;code&gt;authToken&lt;/code&gt; in local storage and add it to the headers. This centralizes your logic and prevents you from having to manually add the token to every single request.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. TanStack Query: A Data Fetching Superpower
&lt;/h2&gt;

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

&lt;p&gt;While &lt;code&gt;useEffect&lt;/code&gt; and &lt;code&gt;useState&lt;/code&gt; work for simple requests, they quickly become complex for managing a real-world application. You have to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loading and error states for each component.&lt;/li&gt;
&lt;li&gt;Caching data to avoid redundant requests.&lt;/li&gt;
&lt;li&gt;Background refetching to keep data fresh.&lt;/li&gt;
&lt;li&gt;Invalidating and updating the cache after a POST, PUT, or DELETE.&lt;/li&gt;
&lt;li&gt;Handling multiple requests with race conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This leads to a lot of boilerplate and potential bugs. This is where &lt;strong&gt;TanStack Query (formerly React Query)&lt;/strong&gt; shines. It's a library that handles all these complexities for you declaratively. It's not a state management library for all your application's state, but rather for your server state.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem: Native State Management for Caching &amp;amp; Refetching
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This is an example of the kind of boilerplate TanStack Query solves.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;NativeStateManagementExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;shouldRefetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShouldRefetch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Network response was not ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;shouldRefetch&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setShouldRefetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;shouldRefetch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Refresh Data&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution: TanStack Query's &lt;code&gt;useQuery&lt;/code&gt; Hook
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// You'll need to set up a QueryClientProvider at the root of your app&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Network response was not ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TanStackQueryExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refetch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fetchItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Refresh Data&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Power of Caching and Stale-while-revalidate
&lt;/h3&gt;

&lt;p&gt;At its core, TanStack Query is about caching. When a query is first performed, the data is cached under its unique &lt;code&gt;queryKey&lt;/code&gt;. Subsequent requests for the same &lt;code&gt;queryKey&lt;/code&gt; will instantly return the cached data while a new, "stale" request is performed in the background to ensure the data is up to date. This pattern is known as &lt;strong&gt;stale-while-revalidate&lt;/strong&gt; and provides an excellent user experience by making the UI feel instantly responsive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Mutations with &lt;code&gt;useMutation&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;For POST, PUT, and DELETE operations, TanStack Query provides the &lt;code&gt;useMutation&lt;/code&gt; hook. Mutations are treated differently because they modify server-side data. &lt;code&gt;useMutation&lt;/code&gt; gives you a function to trigger the request (&lt;code&gt;mutate&lt;/code&gt;) and provides state variables like &lt;code&gt;isPending&lt;/code&gt; and &lt;code&gt;isSuccess&lt;/code&gt; to manage the UI. Most importantly, it has powerful callback functions like &lt;code&gt;onSuccess&lt;/code&gt; and &lt;code&gt;onError&lt;/code&gt; that allow you to invalidate and refetch related queries, ensuring your UI always reflects the latest server state.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Combining Axios and TanStack Query
&lt;/h2&gt;

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

&lt;p&gt;This is a powerful combination for building robust and developer-friendly applications. Think of it this way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Axios&lt;/strong&gt; handles the "how" of data fetching: a clean, configurable, and robust way to make the actual HTTP call. You define a single Axios instance, which centralizes your base URL, timeouts, and most importantly, request and response interceptors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TanStack Query&lt;/strong&gt; handles the "what" and "when" of data fetching: a declarative way to manage the entire data fetching and synchronization lifecycle. It manages loading states, caching, background refetching, and automatically updates the UI after mutations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example of an Integrated Solution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Axios Instance&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// services/api.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// 'Authorization': `Bearer ${token}` // You could add an auth header here&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;React Component using TanStack Query + Axios&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// components/CombinedExample.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useQueryClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../services/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Our configured Axios instance&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// A reusable function for fetching all items&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// A reusable function for creating an item&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// A reusable function for deleting an item&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deleteItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;itemId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/items/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;itemId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;itemId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CombinedExample&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQueryClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Use TanStack Query to manage the 'GET' request for all items&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fetchItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Use a mutation to handle the 'POST' request&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createMutation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;mutationFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;createItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invalidateQueries&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Use a mutation to handle the 'DELETE' request&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deleteMutation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;mutationFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;deleteItem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invalidateQueries&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCreate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;createMutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New Item From Mutation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleDelete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;deleteMutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-2xl font-bold mb-4"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item List&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCreate&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors"&lt;/span&gt;
      &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Add New Item
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;createMutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-blue-500 mt-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Adding item...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;deleteMutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isPending&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-red-500 mt-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Deleting item...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"mt-4 space-y-2"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex justify-between items-center bg-gray-100 p-3 rounded-md shadow-sm"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text-lg"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
              &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleDelete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
              &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"px-3 py-1 bg-red-500 text-white rounded-md text-sm hover:bg-red-600 transition-colors"&lt;/span&gt;
            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              Delete
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;CombinedExample&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;This final, comprehensive example shows the best of both worlds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Axios&lt;/strong&gt; provides a clean, configurable, and robust way to make the actual HTTP call. The separate &lt;code&gt;api.js&lt;/code&gt; file is a best practice for managing this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TanStack Query&lt;/strong&gt; takes care of all the complex data-fetching state management, caching, and automatic UI updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes your code more readable, efficient, and less prone to bugs. You just tell it what to do (&lt;code&gt;useQuery&lt;/code&gt;, &lt;code&gt;useMutation&lt;/code&gt;), and it handles the rest.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Summary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;fetch&lt;/code&gt; for basics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;Axios&lt;/code&gt; for cleaner syntax &amp;amp; interceptors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;TanStack Query&lt;/code&gt; for caching, refetching &amp;amp; lifecycle management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Combine &lt;code&gt;Axios + TanStack&lt;/code&gt; Query for production-ready apps.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>axios</category>
      <category>tanstack</category>
      <category>javascript</category>
    </item>
    <item>
      <title>💬 From Rejection to Revolution: The Engineering Brilliance Behind WhatsApp</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Sun, 10 Aug 2025 22:45:07 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/from-rejection-to-revolution-the-engineering-brilliance-behind-whatsapp-1ij</link>
      <guid>https://dev.to/alifa_ara_heya/from-rejection-to-revolution-the-engineering-brilliance-behind-whatsapp-1ij</guid>
      <description>&lt;h2&gt;
  
  
  📱 The Incredible Engineering Story Behind WhatsApp
&lt;/h2&gt;

&lt;p&gt;Today I stumbled upon the incredible story behind WhatsApp—one of the most successful instant messaging platforms in history—and found it absolutely captivating.&lt;/p&gt;

&lt;p&gt;Jan Koum, a former Yahoo engineer, was once rejected by Facebook. Ironically, just a few years later, Facebook acquired WhatsApp for a staggering &lt;strong&gt;$19 billion&lt;/strong&gt;. Alongside co-founder Brian Acton, Koum built a product that transformed global communication—and did so with remarkable engineering discipline.&lt;/p&gt;

&lt;p&gt;Here are some key takeaways from WhatsApp’s technical journey that every developer and architect can learn from:&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 1. Single Responsibility Principle
&lt;/h2&gt;

&lt;p&gt;WhatsApp was laser-focused on one goal: &lt;strong&gt;replacing expensive SMS&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
No ads, no social feed, no distractions. This clarity of purpose helped it scale rapidly without compromising user experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ 2. Smart Technology Choices
&lt;/h2&gt;

&lt;p&gt;WhatsApp’s backend was built using &lt;strong&gt;Erlang&lt;/strong&gt;, a language designed for massive concurrency.&lt;br&gt;&lt;br&gt;
Unlike Java or C++, Erlang’s lightweight processes are managed by its own virtual machine (BEAM), allowing &lt;strong&gt;millions of simultaneous connections&lt;/strong&gt; with minimal overhead.&lt;br&gt;&lt;br&gt;
This made context switching extremely efficient, enabling WhatsApp to handle real-time messaging at scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 3. Building on Open Source
&lt;/h2&gt;

&lt;p&gt;Rather than reinventing the wheel, WhatsApp was built on &lt;strong&gt;Ejabberd&lt;/strong&gt;, an open-source XMPP server written in Erlang.&lt;br&gt;&lt;br&gt;
This decision accelerated development and allowed the team to focus on &lt;strong&gt;performance and reliability&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📈 4. Scaling with Simplicity
&lt;/h2&gt;

&lt;p&gt;WhatsApp initially leaned into &lt;strong&gt;vertical scaling&lt;/strong&gt;—maximizing the power of individual servers—before layering in &lt;strong&gt;horizontal scaling&lt;/strong&gt; as needed.&lt;br&gt;&lt;br&gt;
This hybrid approach kept infrastructure costs and complexity low while supporting &lt;strong&gt;exponential growth&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔁 5. Seamless Deployment
&lt;/h2&gt;

&lt;p&gt;Running on &lt;strong&gt;FreeBSD&lt;/strong&gt;, WhatsApp leveraged Erlang’s &lt;strong&gt;hot code swapping&lt;/strong&gt; to deploy updates with &lt;strong&gt;zero downtime&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
While their CI/CD pipeline wasn’t publicly detailed, their ability to push changes without interrupting service was a testament to thoughtful engineering.&lt;/p&gt;




&lt;h2&gt;
  
  
  👥 6. Small Team, Big Impact
&lt;/h2&gt;

&lt;p&gt;At the time of acquisition, WhatsApp had just &lt;strong&gt;32 engineers&lt;/strong&gt; supporting over &lt;strong&gt;450 million users&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
This wasn’t just lean—it was &lt;strong&gt;legendary&lt;/strong&gt;. A small, focused team with clear goals outperformed giants.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Final Thought
&lt;/h2&gt;

&lt;p&gt;WhatsApp’s story is more than a tale of startup success—it’s a masterclass in &lt;strong&gt;engineering focus&lt;/strong&gt;, &lt;strong&gt;smart choices&lt;/strong&gt;, and &lt;strong&gt;purposeful simplicity&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Whether you're building your own product or scaling an existing one, there’s a lot to learn from how WhatsApp did it.&lt;/p&gt;




&lt;p&gt;🔗 &lt;strong&gt;Read more:&lt;/strong&gt; &lt;a href="https://open.substack.com/pub/systemdesignone/p/whatsapp-engineering?utm_source=share&amp;amp;utm_medium=android&amp;amp;r=63ird5" rel="noopener noreferrer"&gt;WhatsApp Engineering Journey&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>backend</category>
    </item>
    <item>
      <title>Monorepo vs Polyrepo</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Thu, 07 Aug 2025 14:13:54 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/monorepo-vs-polyrepo-4n3f</link>
      <guid>https://dev.to/alifa_ara_heya/monorepo-vs-polyrepo-4n3f</guid>
      <description>&lt;h2&gt;
  
  
  Monorepo vs Polyrepo - Strategies for Organizing Codebases
&lt;/h2&gt;

&lt;p&gt;Monorepo and polyrepo are two different strategies for organizing a codebase within version control systems like Git. The core difference lies in the number of repositories used: one for all projects (monorepo) or one for each project (polyrepo).&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 Feature Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Monorepo&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Polyrepo&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Structure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A single repository contains all projects, libraries, and applications.&lt;/td&gt;
&lt;td&gt;Each project, service, or library has its own independent repository.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code Sharing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easy and immediate. Dependencies can be referenced directly within the repo.&lt;/td&gt;
&lt;td&gt;Difficult. Requires setting up dependency managers and version coordination.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Atomic Commits&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Possible. A single commit can span multiple projects.&lt;/td&gt;
&lt;td&gt;Not possible. Requires separate commits/PRs per repo.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team Autonomy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lower. Changes affect all teams, requiring more coordination.&lt;/td&gt;
&lt;td&gt;Higher. Teams control their own dependencies, cycles, and tooling.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tooling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standardized across all projects.&lt;/td&gt;
&lt;td&gt;Fragmented; each team may use different tools.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Can become challenging without tooling (e.g., Bazel, Nx, Turborepo).&lt;/td&gt;
&lt;td&gt;More scalable for individual projects.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;More complex; changes may trigger builds/tests across the repo.&lt;/td&gt;
&lt;td&gt;Simpler. Each project has its own CI/CD and schedule.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ Monorepo: Pros &amp;amp; Cons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplified dependency management and versioning.&lt;/li&gt;
&lt;li&gt;Easier refactoring and consistent changes across projects.&lt;/li&gt;
&lt;li&gt;Improved visibility and collaboration.&lt;/li&gt;
&lt;li&gt;Centralized tooling and CI/CD pipelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance issues in large repositories (e.g., slow &lt;code&gt;git pull&lt;/code&gt;/clone).&lt;/li&gt;
&lt;li&gt;Harder access control (typically at the repo level).&lt;/li&gt;
&lt;li&gt;Requires specialized tooling to manage builds efficiently.&lt;/li&gt;
&lt;li&gt;A single bug in shared code can affect multiple projects.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Polyrepo: Pros &amp;amp; Cons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High team autonomy and independent release cycles.&lt;/li&gt;
&lt;li&gt;Granular access control and simpler project management.&lt;/li&gt;
&lt;li&gt;Faster builds and git operations.&lt;/li&gt;
&lt;li&gt;Bugs are isolated to individual projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code duplication and inconsistency.&lt;/li&gt;
&lt;li&gt;Complex dependency management and coordination.&lt;/li&gt;
&lt;li&gt;Overhead in managing multiple CI/CD pipelines and tooling.&lt;/li&gt;
&lt;li&gt;Can lead to team silos and hinder collaboration.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>softwaredevelopment</category>
      <category>git</category>
    </item>
    <item>
      <title>Monolith vs. Microservices: Choosing a Software Architecture</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Thu, 07 Aug 2025 14:08:36 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/monolith-vs-microservices-choosing-a-software-architecture-401n</link>
      <guid>https://dev.to/alifa_ara_heya/monolith-vs-microservices-choosing-a-software-architecture-401n</guid>
      <description>&lt;p&gt;Choosing between a &lt;strong&gt;monolithic&lt;/strong&gt; and &lt;strong&gt;microservices&lt;/strong&gt; architecture is a fundamental decision in software development. Each approach has distinct advantages and disadvantages that impact development, scalability, and maintenance.&lt;/p&gt;




&lt;h3&gt;
  
  
  Monolithic Architecture
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;monolithic&lt;/strong&gt; architecture is a traditional, unified approach where all components of an application are bundled into a single unit. It's a single, self-contained entity.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Characteristics
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single Codebase:&lt;/strong&gt; All code resides in one large project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tightly Coupled:&lt;/strong&gt; Components are closely intertwined and share a single process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Deployment:&lt;/strong&gt; The entire application is built and deployed as a single artifact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity:&lt;/strong&gt; Easier to develop, test, and deploy initially.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Communication between components is faster as it happens within the same process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralized Management:&lt;/strong&gt; Easier to manage a single codebase and deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; The entire application must be scaled, even if only one part requires more resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance:&lt;/strong&gt; A small change in one module can require a full re-deployment of the entire application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology Lock-in:&lt;/strong&gt; Difficult to use different technologies for different parts of the application.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Microservices Architecture
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;microservices&lt;/strong&gt; architecture is a modern, distributed approach where an application is composed of many small, independent services. Each service performs a specific business function.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Characteristics
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Codebases:&lt;/strong&gt; Each service has its own codebase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loosely Coupled:&lt;/strong&gt; Services communicate with each other through APIs (e.g., REST, gRPC).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Independent Deployment:&lt;/strong&gt; Each service can be built, deployed, and scaled independently.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; Individual services can be scaled independently, optimizing resource usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resilience:&lt;/strong&gt; The failure of one service does not necessarily bring down the entire application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology Diversity:&lt;/strong&gt; Different services can be built using different technologies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easier Maintenance:&lt;/strong&gt; Smaller, focused codebases are easier to understand and maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexity:&lt;/strong&gt; Managing a distributed system with multiple services is more complex.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication Overhead:&lt;/strong&gt; Network latency and API calls introduce overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging:&lt;/strong&gt; Tracing issues across multiple services can be challenging.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Comparison at a Glance
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Monolithic&lt;/th&gt;
&lt;th&gt;Microservices&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Structure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single, unified application&lt;/td&gt;
&lt;td&gt;Collection of small, independent services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scale the entire application&lt;/td&gt;
&lt;td&gt;Scale individual services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single deployment&lt;/td&gt;
&lt;td&gt;Independent deployments for each service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Coupling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tightly coupled&lt;/td&gt;
&lt;td&gt;Loosely coupled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lower (initial)&lt;/td&gt;
&lt;td&gt;Higher (initial and ongoing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Small to medium-sized projects, startups&lt;/td&gt;
&lt;td&gt;Large, complex applications; teams with specialized roles&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The choice between monolith and microservices depends on the project's scale, team size, and long-term goals. While a &lt;strong&gt;monolith&lt;/strong&gt; offers simplicity and is often a great starting point for new projects, a &lt;strong&gt;microservices&lt;/strong&gt; architecture provides the flexibility and scalability needed for large, evolving applications. Many companies start with a monolith and transition to microservices as their application grows, a strategy often called "monolith-to-microservices."&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>How I Implemented Google Authentication: A Step-by-Step Guide</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Mon, 21 Jul 2025 15:55:15 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/how-i-implemented-google-authentication-a-step-by-step-guide-1ll9</link>
      <guid>https://dev.to/alifa_ara_heya/how-i-implemented-google-authentication-a-step-by-step-guide-1ll9</guid>
      <description>&lt;h1&gt;
  
  
  Google Authentication Setup: A Step-by-Step Guide
&lt;/h1&gt;

&lt;p&gt;This guide outlines the process of implementing a "Login with Google" feature in a Node.js/Express application using Passport.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Setting Up the Foundation with Middleware
&lt;/h2&gt;

&lt;p&gt;The foundation is established in the main &lt;code&gt;app.ts&lt;/code&gt; file by configuring the necessary middleware for Passport to function correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// d:\L2-programming-hero\backend-tour-management-system\src\app.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/routes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;globalErrorHandler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/middlewares/globalErrorHandler&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;notFound&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/middlewares/notfound&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cookieParser&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cookie-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;passport&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;passport&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;expressSession&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-session&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// import passport config&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/config/passport&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;envVars&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./app/config/env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Configure express-session for Passport&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;expressSession&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;envVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EXPRESS_SESSION_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;resave&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;saveUninitialized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize Passport and its session handling&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;session&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cookieParser&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// ... other middleware and routes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Express Session&lt;/strong&gt;: The &lt;code&gt;express-session&lt;/code&gt; middleware is added. Passport uses this to maintain a login session for the user during the OAuth handshake with Google. It is secured with a secret sourced from environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passport Initialization&lt;/strong&gt;: Passport is initialized with &lt;code&gt;passport.initialize()&lt;/code&gt; and its session handling is enabled with &lt;code&gt;passport.session()&lt;/code&gt;. This hooks Passport into the Express request-response cycle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passport Configuration&lt;/strong&gt;: The line &lt;code&gt;import "./app/config/passport"&lt;/code&gt; is a crucial step. This imported file contains the core Passport strategy configuration. Within this configuration, the &lt;code&gt;GoogleStrategy&lt;/code&gt; is defined, the Google Client ID and Secret are provided, and the verify callback function is implemented. This function is responsible for finding or creating a user in the database based on the profile information returned by Google.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cookie Parser&lt;/strong&gt;: &lt;code&gt;cookie-parser&lt;/code&gt; is included to facilitate setting custom JSON Web Tokens (JWTs) in browser cookies after a successful login.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: Creating the "Login with Google" Route
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;auth.route.ts&lt;/code&gt;, an endpoint is defined for initiating the Google login process from the frontend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// d:\L2-programming-hero\backend-tour-management-system\src\app\modules\auth\auth.route.ts&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/google&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redirect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redirect&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;profile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;redirect&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When a request is made to &lt;code&gt;/api/v1/auth/google&lt;/code&gt;, the &lt;code&gt;passport.authenticate('google', ...)&lt;/code&gt; middleware is triggered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;scope&lt;/code&gt;&lt;/strong&gt;: The scope is set to &lt;code&gt;["profile", "email"]&lt;/code&gt;. This informs Google that the application is requesting permission to access the user's basic profile information (like name and picture) and their email address.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;state&lt;/code&gt;&lt;/strong&gt;: This option provides an enhanced user experience. A &lt;code&gt;redirect&lt;/code&gt; query parameter from the frontend can be captured and passed as the &lt;code&gt;state&lt;/code&gt;. This allows the frontend to specify where the user should be redirected after a successful login (e.g., &lt;code&gt;/my-tours&lt;/code&gt;). Google includes this &lt;code&gt;state&lt;/code&gt; value in the callback request.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This route redirects the user from the application to Google's standard login page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Handling the Callback from Google
&lt;/h2&gt;

&lt;p&gt;After the user authenticates with Google and grants permission, Google redirects them back to a predefined callback URL. A route is defined to handle this callback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// d:\L2-programming-hero\backend-tour-management-system\src\app\modules\auth\auth.route.ts&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/google/callback&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;failureRedirect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="c1"&gt;// Handle failed authentication&lt;/span&gt;
  &lt;span class="nx"&gt;AuthControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;googleCallbackController&lt;/span&gt; &lt;span class="c1"&gt;// Handle successful authentication&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This route, &lt;code&gt;/api/v1/auth/google/callback&lt;/code&gt;, is protected by the same &lt;code&gt;passport.authenticate('google', ...)&lt;/code&gt; middleware. In this context, Passport's role is to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Take the authorization code from Google's response.&lt;/li&gt;
&lt;li&gt; Exchange it for an access token and user profile information behind the scenes.&lt;/li&gt;
&lt;li&gt; Invoke the verify function defined in the &lt;code&gt;passport.ts&lt;/code&gt; configuration.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;If the authentication fails (e.g., the user denies access), the &lt;code&gt;failureRedirect: "/login"&lt;/code&gt; option sends the user back to a login page on the frontend.&lt;/li&gt;
&lt;li&gt;Upon success, Passport attaches the user object (retrieved from the database) to &lt;code&gt;req.user&lt;/code&gt; and passes control to the &lt;code&gt;googleCallbackController&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Finalizing Login and Redirecting the User
&lt;/h2&gt;

&lt;p&gt;The final step occurs in &lt;code&gt;auth.controller.ts&lt;/code&gt;, where the authenticated user from Passport is processed, an application-specific session is created, and the user is redirected back to the frontend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// d:\L2-programming-hero\backend-tour-management-system\src\app\modules\auth\auth.controller.ts&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;googleCallbackController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;catchAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Retrieve the original redirect path from the state query parameter&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;redirectTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;redirectTo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;redirectTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redirectTo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Get the user object attached by Passport&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;httpStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NOT_FOUND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User Not Found&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Create application-specific JWTs&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tokenInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createUserTokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Set JWTs as secure, httpOnly cookies&lt;/span&gt;
    &lt;span class="nf"&gt;setAuthCookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Redirect the user back to the frontend&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;envVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FRONTEND_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;redirectTo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Get User and Redirect Path&lt;/strong&gt;: The user object is retrieved from &lt;code&gt;req.user&lt;/code&gt;, and the original redirect path is extracted from &lt;code&gt;req.query.state&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Create JWTs&lt;/strong&gt;: The &lt;code&gt;createUserTokens(user)&lt;/code&gt; utility is called. This represents a key transition from Google's OAuth flow to the application's own JWT-based authentication system. This function generates a custom &lt;code&gt;accessToken&lt;/code&gt; and &lt;code&gt;refreshToken&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Set Secure Cookies&lt;/strong&gt;: The &lt;code&gt;setAuthCookie(res, tokenInfo)&lt;/code&gt; utility is used to securely set the &lt;code&gt;accessToken&lt;/code&gt; and &lt;code&gt;refreshToken&lt;/code&gt; as &lt;code&gt;httpOnly&lt;/code&gt; cookies in the user's browser.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Redirect to Frontend&lt;/strong&gt;: Finally, the user is redirected back to the frontend application, completing the login flow. For example, if the original path was &lt;code&gt;/my-tours&lt;/code&gt;, the user would be sent to &lt;code&gt;https://my-frontend-app.com/my-tours&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, the user is successfully logged in, and the frontend can use the tokens (stored in cookies) to make authenticated API requests.&lt;/p&gt;

</description>
      <category>authentication</category>
      <category>express</category>
      <category>typescri</category>
      <category>passport</category>
    </item>
    <item>
      <title>How I implemented Access Token and Refresh Token in my Tour Management System Application</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Fri, 18 Jul 2025 23:53:36 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/how-i-implemented-access-token-and-refresh-token-in-my-tour-management-system-application-14b3</link>
      <guid>https://dev.to/alifa_ara_heya/how-i-implemented-access-token-and-refresh-token-in-my-tour-management-system-application-14b3</guid>
      <description>&lt;h2&gt;
  
  
  Authentication Flow: Two-Token Strategy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/alifa-ara-heya/dreamTour-management-system-backend" rel="noopener noreferrer"&gt;Github Code Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this application, we employ a &lt;strong&gt;two-token strategy&lt;/strong&gt; for authentication to enhance security and user experience. This involves an &lt;strong&gt;Access Token&lt;/strong&gt; and a &lt;strong&gt;Refresh Token&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📜 Token Overview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔑 Access Token
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;short-lived JSON Web Token (JWT)&lt;/strong&gt; that the client sends with every request to access protected resources.&lt;/li&gt;
&lt;li&gt;Its short lifespan (defined by &lt;code&gt;JWT_ACCESS_EXPIRES&lt;/code&gt; in &lt;code&gt;env.ts&lt;/code&gt;) minimizes the risk if it's ever compromised.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔄 Refresh Token
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;long-lived JWT&lt;/strong&gt; used solely to obtain a new access token when the old one expires.&lt;/li&gt;
&lt;li&gt;It is stored securely in an &lt;strong&gt;httpOnly cookie&lt;/strong&gt;, making it inaccessible to client-side JavaScript.&lt;/li&gt;
&lt;li&gt;Its longer lifespan is defined by &lt;code&gt;JWT_REFRESH_EXPIRES&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔥 The Complete Authentication and Refresh Flow
&lt;/h2&gt;

&lt;p&gt;Here is the step-by-step process from initial login to session renewal.&lt;/p&gt;




&lt;h3&gt;
  
  
  1️⃣ User Login
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A user submits their credentials (e.g., email/password or through Google OAuth) to a login endpoint like:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  /api/v1/auth/login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The server validates these credentials against the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Upon successful validation, the server generates two tokens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new &lt;strong&gt;Access Token&lt;/strong&gt;, signed with &lt;code&gt;JWT_ACCESS_SECRET&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A new &lt;strong&gt;Refresh Token&lt;/strong&gt;, signed with &lt;code&gt;JWT_REFRESH_SECRET&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;The server sends its response:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Access Token&lt;/strong&gt; is sent in the JSON body of the response. The frontend stores it (e.g., in memory).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refresh Token&lt;/strong&gt; is sent back in an &lt;strong&gt;httpOnly cookie&lt;/strong&gt;. The &lt;code&gt;cookieParser&lt;/code&gt; middleware in &lt;code&gt;app.ts&lt;/code&gt; is essential for the server to read this cookie in subsequent requests.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  2️⃣ Accessing Protected Routes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To make a request to a protected API endpoint (e.g., &lt;code&gt;/api/v1/bookings&lt;/code&gt;), the frontend client attaches the Access Token to the Authorization header:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Authorization: Bearer &amp;lt;access_token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Backend middleware:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intercepts the request.&lt;/li&gt;
&lt;li&gt;Verifies the Bearer token's signature and expiration date.&lt;/li&gt;
&lt;li&gt;If valid, allows the request to proceed to the controller.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  3️⃣ Handling an Expired Access Token
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Eventually, the short-lived Access Token will expire.&lt;/li&gt;
&lt;li&gt;When the client sends a request with the expired token, the backend responds with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;  &lt;/span&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;401&lt;/span&gt; &lt;span class="ne"&gt;Unauthorized&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4️⃣ The Refresh Token Flow (The Core Logic)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When the frontend receives a 401 response, it knows to request a new access token.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It sends a POST request to:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  /api/v1/auth/refresh-token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This request does &lt;strong&gt;not&lt;/strong&gt; require an Authorization header. The browser automatically includes the httpOnly cookie containing the Refresh Token.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Backend process:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses &lt;code&gt;cookieParser&lt;/code&gt; to extract the refresh token from cookies.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verifies the refresh token:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checks signature with &lt;code&gt;JWT_REFRESH_SECRET&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Checks expiration.&lt;/li&gt;
&lt;li&gt;Optionally confirms the user still exists and is active in the database.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;If valid:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generates a new Access Token (signed with &lt;code&gt;JWT_ACCESS_SECRET&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Sends it back in the JSON response body.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  5️⃣ Resuming the Session
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The frontend receives the new Access Token.&lt;/li&gt;
&lt;li&gt;It updates its stored Access Token.&lt;/li&gt;
&lt;li&gt;Automatically retries the original failed API request, now with a valid token.&lt;/li&gt;
&lt;li&gt;The user’s session continues seamlessly.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  6️⃣ When the Refresh Token Expires
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If the Refresh Token is expired or invalid, the backend responds with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;  &lt;/span&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;403&lt;/span&gt; &lt;span class="ne"&gt;Forbidden&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The client knows the session is over.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clears user state and redirects to the login page for re-authentication.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚙️ Configuration References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Access Token Expiration:&lt;/strong&gt; &lt;code&gt;JWT_ACCESS_EXPIRES&lt;/code&gt; in &lt;code&gt;env.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refresh Token Expiration:&lt;/strong&gt; &lt;code&gt;JWT_REFRESH_EXPIRES&lt;/code&gt; in &lt;code&gt;env.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets:&lt;/strong&gt; &lt;code&gt;JWT_ACCESS_SECRET&lt;/code&gt;, &lt;code&gt;JWT_REFRESH_SECRET&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Middleware:&lt;/strong&gt; &lt;code&gt;cookieParser&lt;/code&gt; in &lt;code&gt;app.ts&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This entire process provides a secure and smooth authentication experience for the end-user.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>JWT Implementation Walkthrough</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Wed, 16 Jul 2025 06:06:27 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/jwt-implementation-walkthrough-4j0o</link>
      <guid>https://dev.to/alifa_ara_heya/jwt-implementation-walkthrough-4j0o</guid>
      <description>&lt;p&gt;Let’s walk through the JWT process I’ve implemented in my application, how the flow works.&lt;br&gt;
&lt;a href="https://github.com/alifa-ara-heya/dreamTour-management-system-backend" rel="noopener noreferrer"&gt;My Backend API GitHub link&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📝 A Quick Refresher on JWTs
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;JSON Web Token (JWT)&lt;/strong&gt; is a standard I’m using to securely transmit information between my client and server. It’s essentially a signed, self-contained JSON object.&lt;/p&gt;

&lt;p&gt;Because it’s signed with a secret key that only my server knows, I can trust the information within it.&lt;/p&gt;

&lt;h3&gt;
  
  
  📦 JWT Structure
&lt;/h3&gt;

&lt;p&gt;It has three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Header&lt;/strong&gt;
Metadata about the token (e.g., algorithm &lt;code&gt;HS256&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload&lt;/strong&gt;
The data I want to send (claims), like &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, and &lt;code&gt;role&lt;/code&gt;, plus standard claims like &lt;code&gt;exp&lt;/code&gt; (expiration time).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signature&lt;/strong&gt;
Ensures the token’s integrity. Created using the header, payload, and my secret key.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🚀 The JWT Flow I’ve Built
&lt;/h2&gt;

&lt;p&gt;Here is the step-by-step flow of how I am using JWTs in my code.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Step 1: Generate Token on Login
&lt;/h3&gt;

&lt;p&gt;This is where my user gets their credentials for accessing protected parts of the API.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Login Request&lt;/strong&gt;&lt;br&gt;
A user submits their email and password to my &lt;code&gt;/api/v1/auth/login&lt;/code&gt; endpoint.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Service Logic (&lt;code&gt;auth.service.ts&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;credentialsLogin&lt;/code&gt; service finds the user in the database.&lt;/li&gt;
&lt;li&gt;Securely compares the submitted password with the stored hash using &lt;code&gt;bcryptjs.compare&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Creates a &lt;code&gt;jwtPayload&lt;/code&gt; object with only necessary, non-sensitive data.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwtPayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isUserExist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isUserExist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isUserExist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Signing the Token (&lt;code&gt;utils/jwt.ts&lt;/code&gt;)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I call my generateToken utility. It's great that I've abstracted this into a separate utility file to keep my code clean.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uses &lt;code&gt;jsonwebtoken&lt;/code&gt; to sign the payload with &lt;code&gt;JWT_ACCESS_SECRET&lt;/code&gt; and sets an expiration time from my &lt;code&gt;.env&lt;/code&gt; variables..&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Sending the Token&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Sends the newly created &lt;code&gt;accessToken&lt;/code&gt; back to the client. The client stores it for future requests.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔐 Step 2: Client Accesses a Protected Route
&lt;/h3&gt;

&lt;p&gt;Now, the user wants to do something that requires authentication, like updating their profile.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The client sends a PATCH request to &lt;code&gt;/api/v1/user/:id&lt;/code&gt; with the &lt;code&gt;accessToken&lt;/code&gt; in the Authorization header, typically as &lt;code&gt;Bearer &amp;lt;token&amp;gt;&lt;/code&gt;.:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Middleware Intercepts (&lt;code&gt;user.route.ts&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The request passes through the &lt;code&gt;checkAuth&lt;/code&gt; middleware before hitting the controller.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🛡 Step 3: Verify the Token and Authorize the User (&lt;code&gt;checkAuth.ts&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This middleware is the heart of the API’s security.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A Flexible Higher-Order Function&lt;/strong&gt;&lt;br&gt;
I designed &lt;code&gt;checkAuth&lt;/code&gt; as a higher-order function. It accepts a list of roles (&lt;code&gt;...authRoles&lt;/code&gt;) and returns an Express middleware function. This makes it incredibly powerful and reusable. For instance, to protect an admin-only route, I simply use &lt;code&gt;checkAuth(Role.ADMIN, Role.SUPER_ADMIN)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token Extraction&lt;/strong&gt;&lt;br&gt;
My middleware first looks for the Authorization header and extracts the token.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token Verification&lt;/strong&gt;&lt;br&gt;
It then calls my &lt;code&gt;verifyToken&lt;/code&gt; utility function.&lt;br&gt;
This function uses &lt;code&gt;jwt.verify()&lt;/code&gt; with the same &lt;code&gt;JWT_ACCESS_SECRET&lt;/code&gt;. This single call verifies both the signature (ensuring it’s not tampered with) and the expiration date.&lt;br&gt;
If the token is invalid for any reason, &lt;code&gt;jwt.verify()&lt;/code&gt; throws an error, which my catch block sends to my &lt;code&gt;globalErrorHandler&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Role-Based Authorization&lt;/strong&gt;&lt;br&gt;
If the token is valid, I then check if the user’s role (from the decoded token) is included in the &lt;code&gt;authRoles&lt;/code&gt; I passed to the middleware. If not, I throw a "Forbidden" error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attaching the User to the Request&lt;/strong&gt;&lt;br&gt;
This is a key pattern I’ve implemented. After successful verification and authorization, I attach the entire decoded payload to the Express &lt;code&gt;Request&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;verifiedToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// declared globally in src/app/interfaces/index.d.ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🏗 Step 4: Controller and Service Use Authenticated User
&lt;/h3&gt;

&lt;p&gt;Because of the work I did in the middleware, my controller logic is now much cleaner.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accessing the User in the Controller (&lt;code&gt;user.controller.ts&lt;/code&gt;)&lt;/strong&gt;
In my updateUser controller, I can now trust that req.user exists and contains the authenticated user's data. I don't need to re-verify the token here.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;verifiedToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;This&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;fully&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;safe&lt;/span&gt; &lt;span class="nx"&gt;because&lt;/span&gt; &lt;span class="nx"&gt;I&lt;/span&gt; &lt;span class="nx"&gt;cleverly&lt;/span&gt; &lt;span class="nx"&gt;extended&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="nx"&gt;Express&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;backend&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;tour&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;managemnet&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;system&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;interfaces&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Service-Layer Logic (&lt;code&gt;user.service.ts&lt;/code&gt;)&lt;/strong&gt;
I pass this trusted &lt;code&gt;verifiedToken&lt;/code&gt; to my service layer, where I can implement fine-grained business logic, such as checking if an &lt;code&gt;ADMIN&lt;/code&gt; is trying to modify a SUPER_ADMIN.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This entire flow is &lt;strong&gt;robust&lt;/strong&gt; and &lt;strong&gt;secure&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>jwt</category>
    </item>
    <item>
      <title>JWT Token vs. Session token vs. Refresh Token</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Wed, 16 Jul 2025 05:56:34 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/jwt-token-vs-session-token-vs-refresh-token-47gk</link>
      <guid>https://dev.to/alifa_ara_heya/jwt-token-vs-session-token-vs-refresh-token-47gk</guid>
      <description>&lt;h2&gt;
  
  
  ⚖️ Session Tokens vs. JWT Implementation vs. Refresh Tokens
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Session Tokens (Traditional)&lt;/th&gt;
&lt;th&gt;JWT (Stateless)&lt;/th&gt;
&lt;th&gt;JWT + Refresh Token&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stateful (Server stores session data)&lt;/td&gt;
&lt;td&gt;Stateless (No server storage needed)&lt;/td&gt;
&lt;td&gt;Stateless for access, stateful for refresh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Server stores session info securely&lt;/td&gt;
&lt;td&gt;User’s claims in token payload&lt;/td&gt;
&lt;td&gt;Short-lived access token + long-lived refresh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Needs sticky sessions or shared store&lt;/td&gt;
&lt;td&gt;Highly scalable; any server can validate token&lt;/td&gt;
&lt;td&gt;Refresh tokens allow scaling with security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Session ID reveals nothing (random pointer)&lt;/td&gt;
&lt;td&gt;Payload visible (Base64), no sensitive data&lt;/td&gt;
&lt;td&gt;Refresh token stored securely (httpOnly cookie)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Expiration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Controlled by server session timeout&lt;/td&gt;
&lt;td&gt;Fixed expiration in JWT&lt;/td&gt;
&lt;td&gt;Access token expires quickly; refresh token rotates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vulnerable To&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;CSRF (if not using same-site cookies)&lt;/td&gt;
&lt;td&gt;XSS (if token in localStorage)&lt;/td&gt;
&lt;td&gt;XSS for access tokens, mitigated by refresh flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;When to Use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Monolithic apps, simple setups&lt;/td&gt;
&lt;td&gt;APIs, microservices, mobile apps&lt;/td&gt;
&lt;td&gt;When you want both scalability and strong security&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  🔄 When and Why Use Refresh Tokens?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;br&gt;
Since access tokens in JWT are short-lived (for security), refresh tokens allow the client to silently obtain new access tokens without forcing the user to log in again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;When?&lt;/strong&gt;&lt;br&gt;
Use refresh tokens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For long-lived sessions without sacrificing statelessness.&lt;/li&gt;
&lt;li&gt;In mobile and SPAs (Single Page Applications) where users expect to stay logged in.&lt;/li&gt;
&lt;li&gt;When access tokens are stored in memory or localStorage and refresh tokens in secure httpOnly cookies.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ When and Why Use Session Tokens
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 &lt;strong&gt;When to Use&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;For &lt;strong&gt;monolithic web apps&lt;/strong&gt; (server-rendered pages).&lt;/li&gt;
&lt;li&gt;When you &lt;strong&gt;control both frontend and backend&lt;/strong&gt; tightly.&lt;/li&gt;
&lt;li&gt;If you can use &lt;strong&gt;httpOnly cookies&lt;/strong&gt; for extra security.&lt;/li&gt;
&lt;li&gt;Apps where &lt;strong&gt;cross-site requests&lt;/strong&gt; (forms, etc.) are common and CSRF protections are needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  💡 &lt;strong&gt;Why&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Simple to implement with browser’s built-in cookie handling.&lt;/li&gt;
&lt;li&gt;Session data stays &lt;strong&gt;server-side&lt;/strong&gt;, reducing exposure of user data.&lt;/li&gt;
&lt;li&gt;Works well for small-scale apps or systems without horizontal scaling needs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔑 When and Why Use JWT (Access Token Only)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 &lt;strong&gt;When to Use&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;For &lt;strong&gt;RESTful APIs&lt;/strong&gt; and &lt;strong&gt;microservices&lt;/strong&gt; architectures.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;mobile apps&lt;/strong&gt; or &lt;strong&gt;SPAs (Single Page Applications)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;When clients don’t need long-lived sessions.&lt;/li&gt;
&lt;li&gt;If you need a &lt;strong&gt;stateless backend&lt;/strong&gt; (no session store).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  💡 &lt;strong&gt;Why&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Highly scalable since no state is stored on the server.&lt;/li&gt;
&lt;li&gt;Any server instance can validate the token with the secret key.&lt;/li&gt;
&lt;li&gt;Ideal for distributed systems and modern API-first designs.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔄 When and Why Use JWT + Refresh Token
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 &lt;strong&gt;When to Use&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;When you want &lt;strong&gt;short-lived access tokens&lt;/strong&gt; but also &lt;strong&gt;long-lived sessions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;For &lt;strong&gt;mobile apps&lt;/strong&gt;, &lt;strong&gt;SPAs&lt;/strong&gt;, or systems where users expect to stay logged in.&lt;/li&gt;
&lt;li&gt;To mitigate risks of storing tokens in memory or localStorage.&lt;/li&gt;
&lt;li&gt;When &lt;strong&gt;rotating tokens&lt;/strong&gt; improves security.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  💡 &lt;strong&gt;Why&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Balances &lt;strong&gt;security&lt;/strong&gt; (short access token lifetime) and &lt;strong&gt;user convenience&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Refresh token stays securely in httpOnly cookies, reducing XSS risks.&lt;/li&gt;
&lt;li&gt;Allows silent re-authentication without frequent logins.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>jwt</category>
      <category>session</category>
      <category>token</category>
    </item>
    <item>
      <title>Dream Tour Management Backend Development – Part 1: Foundational Setup</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Sun, 13 Jul 2025 02:34:35 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/dreamtourmanagement-backend-part-1-progress-recap-nog</link>
      <guid>https://dev.to/alifa_ara_heya/dreamtourmanagement-backend-part-1-progress-recap-nog</guid>
      <description>&lt;p&gt;This is a progress recap of Part 1 of the backend development for the &lt;strong&gt;DreamTourManagement&lt;/strong&gt; system. The goal was to set up a clean, scalable, and production-ready Express.js architecture using TypeScript, Zod, and modular patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Step-by-Step Implementation Journey
&lt;/h2&gt;

&lt;p&gt;Here’s the logical order in which the backend was built.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Step 1: Core Application Setup
&lt;/h3&gt;

&lt;p&gt;This step established the basic server infrastructure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Express Server (&lt;code&gt;app.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The Express app was initialized with essential middleware:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;express.json()&lt;/code&gt; for parsing JSON request bodies
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cors()&lt;/code&gt; for enabling cross-origin requests&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database Connection (&lt;code&gt;server.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;
Mongoose was configured to connect to MongoDB. The server only starts if the database connection succeeds.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Environment Configuration (&lt;code&gt;app/config/env.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;
A type-safe system was created to manage environment variables like &lt;code&gt;PORT&lt;/code&gt;, &lt;code&gt;DB_URL&lt;/code&gt;, etc., ensuring better security and easier environment switching (dev, prod).&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  👤 Step 2: Building the First Feature Module – User
&lt;/h3&gt;

&lt;p&gt;The user module was used as a pattern for all future modules. This modular architecture helps in scaling and maintaining the app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interface (&lt;code&gt;user.interface.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Defined the &lt;code&gt;IUser&lt;/code&gt; interface with proper typing for consistent and type-safe data across the app.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Model (&lt;code&gt;user.model.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Created a Mongoose &lt;code&gt;userSchema&lt;/code&gt; with field rules like required and unique constraints.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Service (&lt;code&gt;user.service.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Contains business logic like &lt;code&gt;User.create()&lt;/code&gt; and &lt;code&gt;User.find()&lt;/code&gt;. It acts as the “brain” behind each module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Controller (&lt;code&gt;user.controller.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Acts as the middle layer between HTTP requests and services. Handles incoming data and formats outgoing responses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Route (&lt;code&gt;user.route.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sets up REST endpoints such as &lt;code&gt;POST /register&lt;/code&gt; and &lt;code&gt;GET /all-users&lt;/code&gt; and connects them to controller functions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧱 Step 3: Architecting for Scalability
&lt;/h3&gt;

&lt;p&gt;With the base module built, scalable patterns were introduced.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Centralized Routing (&lt;code&gt;routes/index.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
All module routes are registered in one place. New routes can be added simply by adding them to a &lt;code&gt;moduleRoutes&lt;/code&gt; array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standardized Response Utility (&lt;code&gt;utils/sendResponse.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A utility to send all success responses in a uniform structure:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;meta&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ⚠️ Step 4: Robust Error Handling System
&lt;/h3&gt;

&lt;p&gt;Handling errors effectively is key to building a stable application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Async Wrapper (&lt;code&gt;utils/catchAsync.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
A higher-order function that wraps async controllers and automatically forwards errors to &lt;code&gt;next()&lt;/code&gt;. This eliminates repetitive &lt;code&gt;try...catch&lt;/code&gt; blocks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Error Class (&lt;code&gt;errorHelpers/appError.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
Extends the built-in &lt;code&gt;Error&lt;/code&gt; class to support custom status codes. Helpful for throwing HTTP-aware errors like &lt;code&gt;new AppError(404, "User not found")&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global Error Handler (&lt;code&gt;middlewares/globalErrorHandler.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
Catches and formats all errors into a consistent JSON response.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not Found Handler (&lt;code&gt;middlewares/notfound.ts&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
Captures all undefined routes and sends a clean &lt;code&gt;404 Not Found&lt;/code&gt; response.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔁 Step 5: Server Stability &amp;amp; Graceful Shutdown
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;server.ts&lt;/code&gt;, listeners were added for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;unhandledRejection&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uncaughtException&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SIGTERM&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These allow the server to exit cleanly in case of unexpected errors or shutdown signals — crucial for production readiness.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 The Complete Request Flow (Example: &lt;code&gt;POST /api/v1/user/register&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Let’s break down what happens from request to response.&lt;/p&gt;

&lt;h3&gt;
  
  
  📥 Request Flow:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A client sends a &lt;code&gt;POST&lt;/code&gt; request with user data to &lt;code&gt;/api/v1/user/register&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;app.ts&lt;/code&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;express.json()&lt;/code&gt; parses the JSON body.&lt;/li&gt;
&lt;li&gt;The route &lt;code&gt;/api/v1/user&lt;/code&gt; is forwarded to the router from &lt;code&gt;routes/index.ts&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;routes/index.ts&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The router matches &lt;code&gt;/user&lt;/code&gt; and forwards to &lt;code&gt;userRoutes&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;user.route.ts&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;POST /register&lt;/code&gt; route is matched.&lt;/li&gt;
&lt;li&gt;Input validation happens here using &lt;code&gt;validateRequest&lt;/code&gt; middleware with a Zod schema.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/register&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nf"&gt;validateRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UserValidations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUserValidationSchema&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
     &lt;span class="nx"&gt;UserControllers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createUser&lt;/span&gt;
   &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;user.controller.ts&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;createUser&lt;/code&gt; controller is wrapped in &lt;code&gt;catchAsync&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It receives the validated &lt;code&gt;req.body&lt;/code&gt;, calls &lt;code&gt;UserServices.createUser()&lt;/code&gt;, and sends a formatted success response via &lt;code&gt;sendResponse&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;user.service.ts&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Handles the actual database logic with &lt;code&gt;User.create()&lt;/code&gt; and returns the new user.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;user.model.ts&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Mongoose validates the data and saves it to the MongoDB &lt;code&gt;users&lt;/code&gt; collection.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ⚠️ Error Flow:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;If Zod validation fails → &lt;code&gt;validateRequest&lt;/code&gt; calls &lt;code&gt;next(error)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If Mongoose fails (e.g., duplicate email) → the promise rejects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;catchAsync&lt;/code&gt; catches and forwards the error to Express.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;globalErrorHandler.ts&lt;/code&gt; receives the error and responds with:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Detailed error message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;only in development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧠 Summary
&lt;/h2&gt;

&lt;p&gt;In Part 1, the focus was on building a &lt;strong&gt;professional-grade foundation&lt;/strong&gt; that supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧩 Modular design&lt;/li&gt;
&lt;li&gt;✅ Consistent responses&lt;/li&gt;
&lt;li&gt;🧪 Centralized validation and error handling&lt;/li&gt;
&lt;li&gt;🧱 Scalable route management&lt;/li&gt;
&lt;li&gt;🧯 Stable production-ready behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this groundwork in place, the application is ready to move on to &lt;strong&gt;authentication, authorization, OTP, and role-based access&lt;/strong&gt; in the next part.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Coming up in Part 2&lt;/strong&gt;:&lt;br&gt;
🔐 Authentication with JWT&lt;br&gt;
📨 OTP system&lt;br&gt;
🛂 Role-based Access Control (Admin, Guide, User)&lt;br&gt;
🧾 Guide approval workflows&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

&lt;p&gt;#nodejs #typescript #expressjs #zod #backend #webdev #cleancode #dreamtourmanagement #programminghero&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>javascript</category>
      <category>express</category>
    </item>
    <item>
      <title>Stop Writing try-catch in Every Express Controller — Use This Pattern Instead!</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Sat, 12 Jul 2025 17:10:24 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/stop-writing-try-catch-in-every-express-controller-use-this-pattern-instead-2dja</link>
      <guid>https://dev.to/alifa_ara_heya/stop-writing-try-catch-in-every-express-controller-use-this-pattern-instead-2dja</guid>
      <description>&lt;p&gt;In Express.js apps, especially when dealing with async operations (like database queries), you've likely repeated the same code structure over and over:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getAllUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UserServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ This works — but do you really want to write that &lt;code&gt;try...catch&lt;/code&gt; block &lt;strong&gt;every single time&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Let’s clean it up using a Higher-Order Function.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚫 The Problem
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Every controller duplicates the same &lt;code&gt;try-catch-next()&lt;/code&gt; logic.&lt;/li&gt;
&lt;li&gt;It violates the &lt;strong&gt;DRY principle&lt;/strong&gt; (Don't Repeat Yourself).&lt;/li&gt;
&lt;li&gt;It clutters your code and distracts from the actual business logic.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ The Solution: &lt;code&gt;catchAsync&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s abstract the error-catching logic into a reusable utility function.&lt;/p&gt;

&lt;p&gt;📁 &lt;code&gt;src/utils/catchAsync.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;RequestHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;catchAsync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RequestHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧠 What's Going On Here? What Is a Higher-Order Function (HOF)?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;catchAsync&lt;/code&gt; function is a &lt;strong&gt;Higher-Order Function (HOF)&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Higher-Order Function&lt;/strong&gt; is simply a function that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Takes another function as an argument&lt;/strong&gt;, or&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Returns a new function&lt;/strong&gt;, or&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does both&lt;/strong&gt; (like &lt;code&gt;catchAsync&lt;/code&gt;!)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🔁 Why are HOFs powerful?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;They allow you to &lt;strong&gt;wrap&lt;/strong&gt; and &lt;strong&gt;enhance&lt;/strong&gt; behavior without repeating code.&lt;/li&gt;
&lt;li&gt;You can build &lt;strong&gt;reusable utilities&lt;/strong&gt; like authentication guards, validators, logging, and — in our case — async error handlers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔍 Deep Dive: How &lt;code&gt;catchAsync&lt;/code&gt; Works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;catchAsync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RequestHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s break this down:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Line&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;catchAsync(fn)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Takes your controller as an argument&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;return (req, res, next)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns a new function with the same signature Express expects&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.resolve(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ensures even non-async handlers are wrapped in a Promise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.catch((err) =&amp;gt; next(err))&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Automatically catches any error and forwards it to Express’s global error handler&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;🧠 So instead of you writing &lt;code&gt;try...catch&lt;/code&gt;, &lt;code&gt;catchAsync&lt;/code&gt; does it for you!&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Cleaner Controller Code
&lt;/h2&gt;

&lt;p&gt;Now your controller becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;catchAsync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../utils/catchAsync&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getAllUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;catchAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UserServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Users retrieved successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ No more &lt;code&gt;try...catch&lt;/code&gt; clutter&lt;br&gt;
✅ Just focus on the actual logic&lt;/p&gt;


&lt;h2&gt;
  
  
  💬 Bonus: Want to Handle Validation or Custom Errors?
&lt;/h2&gt;

&lt;p&gt;You can combine &lt;code&gt;catchAsync&lt;/code&gt; with a custom error class like &lt;code&gt;AppError&lt;/code&gt;. You can read more about it here (&lt;a href="https://dev.to/alifa_ara_heya/building-a-better-apperror-class-in-nodejs-for-robust-api-error-handling-25o"&gt;https://dev.to/alifa_ara_heya/building-a-better-apperror-class-in-nodejs-for-robust-api-error-handling-25o&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User not found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your global error handler can cleanly handle all cases.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 TL;DR
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Repeating try/catch in every controller&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;catchAsync()&lt;/code&gt; to wrap async functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Messy controllers&lt;/td&gt;
&lt;td&gt;Cleaner, focused logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manual error handling&lt;/td&gt;
&lt;td&gt;Automatic forwarding to global error middleware&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;Using &lt;strong&gt;Higher-Order Functions&lt;/strong&gt; like &lt;code&gt;catchAsync&lt;/code&gt; makes your codebase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More readable&lt;/li&gt;
&lt;li&gt;Less error-prone&lt;/li&gt;
&lt;li&gt;Easier to maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a small trick, but it will make your Express codebase much more professional and clean.&lt;/p&gt;

&lt;p&gt;🔁 &lt;strong&gt;Try it out in your next Express project&lt;/strong&gt; and say goodbye to repetitive &lt;code&gt;try...catch&lt;/code&gt; blocks forever!&lt;/p&gt;




&lt;p&gt;#expressjs #javascript #nodejs #backend #cleancode #webdev #devtips&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>express</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Building a Better `AppError` Class in Node.js for Robust API Error Handling</title>
      <dc:creator>Alifa Ara Heya</dc:creator>
      <pubDate>Fri, 11 Jul 2025 23:12:45 +0000</pubDate>
      <link>https://dev.to/alifa_ara_heya/building-a-better-apperror-class-in-nodejs-for-robust-api-error-handling-25o</link>
      <guid>https://dev.to/alifa_ara_heya/building-a-better-apperror-class-in-nodejs-for-robust-api-error-handling-25o</guid>
      <description>&lt;p&gt;When you're building a Node.js API with Express, &lt;strong&gt;error handling is critical&lt;/strong&gt;. You want responses to be:&lt;/p&gt;

&lt;p&gt;✅ Consistent&lt;br&gt;
✅ Predictable&lt;br&gt;
✅ Meaningful for the client&lt;/p&gt;

&lt;p&gt;But JavaScript’s built-in &lt;code&gt;Error&lt;/code&gt; class falls short for APIs — it doesn’t carry the &lt;strong&gt;HTTP status code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;AppError&lt;/code&gt; class extends the built-in &lt;code&gt;Error&lt;/code&gt; to add a &lt;code&gt;statusCode&lt;/code&gt; property. This allows you to create errors that carry their own status code, making your error handling much cleaner and more predictable.&lt;/p&gt;

&lt;p&gt;Let’s build a powerful &lt;code&gt;AppError&lt;/code&gt; class and integrate it cleanly into your Express API.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚫 The Problem with the Default Error Class
&lt;/h2&gt;

&lt;p&gt;Consider this typical controller logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// user.controller.ts&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;UserServices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUserById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User not found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue?&lt;br&gt;
Even though &lt;code&gt;User not found&lt;/code&gt; is a &lt;strong&gt;404&lt;/strong&gt;, we send a &lt;strong&gt;500 Internal Server Error&lt;/strong&gt; — because there's no way to attach the right status code to the error itself.&lt;/p&gt;


&lt;h2&gt;
  
  
  ✅ A First Draft: Creating &lt;code&gt;AppError&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s define a simple custom error class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/errorHelpers/appError.ts&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;captureStackTrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 Explanation: What’s Happening Behind the Scenes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;AppError&lt;/code&gt; Breakdown:
&lt;/h3&gt;

&lt;p&gt;The first line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;declares a new class named &lt;code&gt;AppError&lt;/code&gt; that inherits from the standard JavaScript Error class. This means an &lt;code&gt;AppError&lt;/code&gt; instance will have all the properties and methods of a regular &lt;code&gt;Error&lt;/code&gt; (like .message and .stack), plus any new ones we define.&lt;/p&gt;

&lt;p&gt;The second line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This declares a new public property on the class called &lt;code&gt;statusCode&lt;/code&gt;. This is the key addition that will hold the HTTP status code (e.g., 400, 404, 500).&lt;/p&gt;

&lt;p&gt;The third line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the constructor for the class. It's called whenever you create a new instance with &lt;code&gt;new AppError(...)&lt;/code&gt;. It takes three arguments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;statusCode&lt;/code&gt;: The HTTP status code for this error.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message&lt;/code&gt;: The human-readable error message.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stack&lt;/code&gt; = '': An optional stack trace. If you don't provide one, it will be generated automatically.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is crucial. It calls the constructor of the parent &lt;code&gt;Error&lt;/code&gt; class and passes the message to it. This is what sets the &lt;code&gt;error.message&lt;/code&gt; property correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line assigns the &lt;code&gt;statusCode&lt;/code&gt; passed into the constructor to the &lt;code&gt;statusCode&lt;/code&gt; property of the new &lt;code&gt;AppError&lt;/code&gt; instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;captureStackTrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Constructor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This block handles the stack trace.&lt;/p&gt;

&lt;p&gt;If a &lt;code&gt;stack&lt;/code&gt; string is provided to the constructor, it uses that.&lt;br&gt;
Otherwise, it calls &lt;code&gt;Error.captureStackTrace(this, this. Constructor)&lt;/code&gt;. This is a standard Node.js V8 feature that generates a stack trace for the error. The second argument &lt;code&gt;(this. Constructor)&lt;/code&gt; tells it to exclude the &lt;code&gt;AppError&lt;/code&gt; constructor function from the stack trace, which makes your error logs cleaner and points directly to where the error was created.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why this works:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;this.statusCode = statusCode&lt;/code&gt;: We now attach the right HTTP status code.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Error.captureStackTrace(...)&lt;/code&gt;: This is a standard Node.js practice. It captures the stack trace, excluding the constructor function itself, which makes for cleaner error logs.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  💡 How to Use &lt;code&gt;AppError&lt;/code&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1️⃣ Throwing it in services or controllers:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// user.service.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../errorHelpers/appError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;httpStatus&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http-status-codes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findUserById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AppError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;httpStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NOT_FOUND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User not found!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2️⃣ Handling it globally:
&lt;/h3&gt;

&lt;p&gt;This custom error becomes powerful when used with &lt;code&gt;globalErrorHandler&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// middlewares/globalErrorHandler.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;globalErrorHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Something went wrong!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Now the response reflects the real nature of the error — 404 for missing user, 403 for unauthorized, etc.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Bonus: Cleaner Code, Better API
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;AppError&lt;/code&gt;, your &lt;strong&gt;services are responsible for context&lt;/strong&gt;, and your &lt;strong&gt;global error handler is consistent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Your API becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Easier to maintain&lt;/li&gt;
&lt;li&gt;✅ More readable&lt;/li&gt;
&lt;li&gt;✅ Scalable with different error types (&lt;code&gt;ValidationError&lt;/code&gt;, &lt;code&gt;DatabaseError&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;By creating an &lt;code&gt;AppError&lt;/code&gt; class:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You decouple status code logic from the global handler&lt;/li&gt;
&lt;li&gt;You make services more expressive and controllers leaner&lt;/li&gt;
&lt;li&gt;You set the foundation for &lt;strong&gt;robust, predictable error handling&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Pro tip: You can even extend &lt;code&gt;AppError&lt;/code&gt; into specific subclasses like &lt;code&gt;ValidationError&lt;/code&gt;, &lt;code&gt;AuthError&lt;/code&gt;, etc.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📌 TL;DR
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No HTTP status in &lt;code&gt;Error&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Add &lt;code&gt;statusCode&lt;/code&gt; in &lt;code&gt;AppError&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Messy stack traces&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;Error.captureStackTrace&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guessing error codes&lt;/td&gt;
&lt;td&gt;Define them at the throw site&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By implementing this pattern, you've made your error handling more structured, expressive, and easier to manage.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
      <category>express</category>
    </item>
  </channel>
</rss>
