<?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: Idris Gadi</title>
    <description>The latest articles on DEV Community by Idris Gadi (@igadii).</description>
    <link>https://dev.to/igadii</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%2F1390560%2F6a5aab11-776a-44a6-a1c6-ee0f56d116ec.jpg</url>
      <title>DEV Community: Idris Gadi</title>
      <link>https://dev.to/igadii</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/igadii"/>
    <language>en</language>
    <item>
      <title>10X Developer and the POC Trap</title>
      <dc:creator>Idris Gadi</dc:creator>
      <pubDate>Thu, 04 Dec 2025 15:48:07 +0000</pubDate>
      <link>https://dev.to/igadii/10x-developer-and-the-poc-trap-4cc5</link>
      <guid>https://dev.to/igadii/10x-developer-and-the-poc-trap-4cc5</guid>
      <description>&lt;h5&gt;
  
  
  A tale of POCs, tech debt, and working with rockstars who moved too fast
&lt;/h5&gt;

&lt;h2&gt;
  
  
  Meeting the 10X Dev
&lt;/h2&gt;

&lt;p&gt;In my web development career, I've so far worked with three quote and quote "10X" (or "cracked") developers across three different projects.&lt;/p&gt;

&lt;p&gt;They are amazing at work, complete more tickets per sprint than the rest of the team combined, work 12+ hours a day, skip weekends, rarely take any leave, and most importantly, they can get you a POC in less than a week or two (a bond they might be cursed with forever).&lt;/p&gt;

&lt;h2&gt;
  
  
  POC Hero
&lt;/h2&gt;

&lt;p&gt;A 10X developer’s relationship with POCs often begins with an ambitious feature request.&lt;/p&gt;

&lt;p&gt;The lead proposes that we first make a POC, do some feasibility analysis, and run user acceptance tests. "But we don't have much time", says the product manager. They look at the 10X developer and ask, "We can do this in two weeks, right?".&lt;/p&gt;

&lt;p&gt;The 10X developer grinds for two weeks and delivers a prototype that's “good enough.” It goes into testing and passes with flying colours. The prototype is merged into the main project. Success.&lt;/p&gt;

&lt;p&gt;A new feature request comes in. The POC is assigned to the 10X developer. This time, the prototype didn't pass testing, and the feature is marked not feasible, saving us months of development time. Success again.&lt;/p&gt;

&lt;p&gt;Over time (sprint after sprint), the 10X developer gets assigned more and more POC work. Eventually, they stop doing any bug fixing, enhancements, upgrades, or maintenance. All they do now is create POCs.&lt;/p&gt;

&lt;p&gt;Every big and small feature now needs a POC, and who handles that? Correct: the 10X developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Hero to Bottleneck
&lt;/h2&gt;

&lt;p&gt;As more and more POC work gets assigned, they get less and less time to actually work on it.&lt;/p&gt;

&lt;p&gt;The prototype quality drops from good enough to barely functional, and they start writing clever but garbage code that's hard to understand and a nightmare to maintain. Once the prototype is merged, they don't have time to continue working on that feature, as they have five more POCs to work on. That work is assigned to someone else in the team (yes, sometimes it's you).&lt;/p&gt;

&lt;p&gt;You realise the prototype that was “supposedly” built to handle edge cases barely works even on the happy path. Product believes the prototype accounts for the future specs (developed by the 10X developer), but you only know that it barely covers the current ones.&lt;/p&gt;

&lt;p&gt;They grow out of touch with actual, real-world project work. They now live in the POC world, where everything is a green field project. Their system never breaks; it's always someone else's faulty code. Anyways, they don't have time to fix it. They’ve already got ten more POCs to work on. And now it’s your responsibility to fix it.&lt;/p&gt;

&lt;p&gt;They start shipping more features in a quarter than the rest of the team combined in a year. Meanwhile, you get less and less time to stabilise the prototype and get it into production. The 10X developer assures you it's already “production-ready.” You just need to iron out the cloth, the only issue being, the cloth has multiple holes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Team Fatigue and Burnout
&lt;/h2&gt;

&lt;p&gt;Eventually, everyone on the team starts resenting having to pick up the pieces from the 10X developer's prototypes. No one wants to work with them anymore.&lt;/p&gt;

&lt;p&gt;What was once an outlier becomes the baseline. People start burning out, start leaving the project, and with each departure, the project slips from bearable to broken.&lt;/p&gt;

&lt;p&gt;What was once a thriving codebase and a colourful team becomes a barren, forgotten land.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>development</category>
    </item>
    <item>
      <title>How Scope and Closures Work Together in JavaScript: A Classic Interview Question Explained</title>
      <dc:creator>Idris Gadi</dc:creator>
      <pubDate>Wed, 18 Jun 2025 18:17:00 +0000</pubDate>
      <link>https://dev.to/igadii/how-closures-and-scope-work-together-in-javascript-a-classic-interview-question-explained-2j9o</link>
      <guid>https://dev.to/igadii/how-closures-and-scope-work-together-in-javascript-a-classic-interview-question-explained-2j9o</guid>
      <description>&lt;p&gt;&lt;strong&gt;Scope and Closures&lt;/strong&gt; are two fundamental concepts in JavaScript that often elude even experienced developers, and what’s frequently overlooked is that these two concepts don’t operate in isolation; they usually work hand in hand in real-world JavaScript code.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore how Scope and Closures come into play by breaking down a classic &lt;code&gt;for&lt;/code&gt; loop interview question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;p&gt;Before diving in, you should have a basic understanding of:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Scope" rel="noopener noreferrer"&gt;Scope&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;What is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures" rel="noopener noreferrer"&gt;Closure&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Interview Question
&lt;/h2&gt;

&lt;p&gt;Here’s that classic &lt;code&gt;for&lt;/code&gt; loop interview question that often trips developers up:&lt;br&gt;&lt;br&gt;
&lt;em&gt;Question: What will be the output of the following code?&lt;/em&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="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="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;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A developer unfamiliar with how scope and closures work together might say it will log &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;. Those who understand the behaviour correctly will answer that it logs &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow-up Question: How would you fix this bug?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;The most common solution is to replace the var keyword with let:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &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;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="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;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This change works, but do you understand why it works? That’s where Scope and Closures come into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Scope
&lt;/h2&gt;

&lt;p&gt;To fully understand why this happens, we need to take a step back and consider where the &lt;code&gt;for&lt;/code&gt; loop lives. In real-world code, a &lt;code&gt;for&lt;/code&gt; loop almost always exists inside a function.&lt;/p&gt;

&lt;p&gt;The key point in the original snippet is that &lt;code&gt;var&lt;/code&gt; is &lt;strong&gt;function-scoped&lt;/strong&gt;. Even though &lt;code&gt;i&lt;/code&gt; is declared in the &lt;code&gt;for&lt;/code&gt; loop declaration, it’s scoped to the entire function, not to each iteration of the loop.&lt;/p&gt;

&lt;p&gt;We can rewrite the code like this, and the behaviour remains exactly the same:&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;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="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="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="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="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="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="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, you can see that every &lt;code&gt;setTimeout&lt;/code&gt; callback closes over the same &lt;code&gt;i&lt;/code&gt; variable. In JavaScript, closures don’t copy the value of a variable. Instead, they keep a reference to the original variable. So when the callbacks eventually run, they all see whatever value &lt;code&gt;i&lt;/code&gt; has at that moment.&lt;/p&gt;

&lt;p&gt;Since the loop has already completed by the time the &lt;code&gt;setTimeout&lt;/code&gt; callbacks fire, &lt;code&gt;i&lt;/code&gt; has been incremented to &lt;code&gt;3&lt;/code&gt;. That’s why you see &lt;code&gt;3&lt;/code&gt; printed three times.&lt;/p&gt;

&lt;h2&gt;
  
  
  How &lt;code&gt;let&lt;/code&gt; Solves the Problem
&lt;/h2&gt;

&lt;p&gt;When we replace &lt;code&gt;var&lt;/code&gt; with &lt;code&gt;let&lt;/code&gt;, we’re essentially changing how the variable is scoped and initialised during each iteration of the loop.&lt;/p&gt;

&lt;p&gt;Unlike &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt; is &lt;strong&gt;block-scoped&lt;/strong&gt;. The &lt;code&gt;for&lt;/code&gt; loop creates a new block for each iteration, and &lt;code&gt;let&lt;/code&gt; creates a new binding of &lt;code&gt;i&lt;/code&gt; every time. This is roughly equivalent to writing:&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;function&lt;/span&gt; &lt;span class="nf"&gt;main&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;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="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="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&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;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="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="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&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;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="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="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&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;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you look closely, each &lt;code&gt;setTimeout&lt;/code&gt; still closes over &lt;code&gt;i&lt;/code&gt;, but now &lt;code&gt;i&lt;/code&gt; is a different variable in each block, initialised with the correct value for that iteration. That’s why we get the expected output: &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Closure and Scope Work Together
&lt;/h2&gt;

&lt;p&gt;At the heart of this problem is how &lt;strong&gt;Scope&lt;/strong&gt; and &lt;strong&gt;Closures&lt;/strong&gt; interact.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Scope&lt;/em&gt; determines where a variable is accessible in the code. With &lt;code&gt;var&lt;/code&gt;, the variable is function-scoped, meaning there's only one shared variable throughout the loop. With &lt;code&gt;let&lt;/code&gt;, a new block-scope variable is created for each iteration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Closures&lt;/em&gt; happen when a function "remembers" variables from its surrounding scope, even after that scope has finished executing. In this example, each setTimeout callback forms a closure over &lt;code&gt;i&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When using &lt;code&gt;var&lt;/code&gt;, all the closures refer to the same &lt;code&gt;i&lt;/code&gt;, and since the loop finishes before the timeouts execute, they all log &lt;code&gt;3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When using &lt;code&gt;let&lt;/code&gt;, a new &lt;code&gt;i&lt;/code&gt; is created for each iteration, so each closure captures its own distinct copy of &lt;code&gt;i&lt;/code&gt;. That’s why the output becomes &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgements
&lt;/h2&gt;

&lt;p&gt;This article is heavily inspired by &lt;a href="https://me.getify.com/" rel="noopener noreferrer"&gt;Kyle Simpson's&lt;/a&gt; &lt;a href="https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/scope%20&amp;amp;%20closures/README.md#you-dont-know-js-scope--closures" rel="noopener noreferrer"&gt;"Scope &amp;amp; Closures"&lt;/a&gt; from the "You Don’t Know JS" (YDKJS) series.&lt;br&gt;&lt;br&gt;
Even though I technically knew the answer to this interview question, I struggled to explain why it works that way. That struggle made me realise I didn’t fully understand what was actually happening. The book helped me finally connect the dots.&lt;/p&gt;

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

&lt;p&gt;Understanding how Scope and Closures work together is a crucial part of JavaScript, and struggling with interview questions like this one is a great nudge in the right direction to deepen that understanding.&lt;/p&gt;

&lt;p&gt;If you enjoyed this article, feel free to connect with me on &lt;a href="https://www.linkedin.com/in/idris-gadi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, follow me on &lt;a href="https://x.com/igadii_X" rel="noopener noreferrer"&gt;X/Twitter&lt;/a&gt;, or find me on &lt;a href="https://bsky.app/profile/igadii.bsky.social" rel="noopener noreferrer"&gt;Bluesky&lt;/a&gt;. I regularly share posts like this and share lessons from my learning journey.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>learning</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building Efficient Node.js Workflows in GitHub Actions: Leveraging Caching and Modular Job Structures</title>
      <dc:creator>Idris Gadi</dc:creator>
      <pubDate>Fri, 08 Nov 2024 08:28:48 +0000</pubDate>
      <link>https://dev.to/igadii/building-efficient-nodejs-workflows-in-github-actions-leveraging-caching-and-modular-job-structures-4gd6</link>
      <guid>https://dev.to/igadii/building-efficient-nodejs-workflows-in-github-actions-leveraging-caching-and-modular-job-structures-4gd6</guid>
      <description>&lt;p&gt;As Software Developers, we love automation, be it automating tasks or using that automation. One such automation is CI/CD pipelines, and one of the most widely used platforms is GitHub Actions.  &lt;/p&gt;

&lt;p&gt;It is crucial to learn the platform that we are using and the features that it offers to build efficient and reliable automation.  &lt;/p&gt;

&lt;p&gt;One of the most common automation workflows used in Git-based Software Development is PR/MR checks, these checks have become an essential part of modern CI pipelines, as they help maintain the source code and improve PR/MR reviews.  &lt;/p&gt;

&lt;p&gt;In this article, we will focus on creating a PR-checks workflow for a Node.js application using GitHub Actions, and how we can improve the Developer Experience(DX) and make it even more efficient using modular jobs, and caching.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is &lt;a href="https://docs.github.com/en/actions/about-github-actions/understanding-github-actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;How to create a Github Actions workflow. &lt;a href="https://docs.github.com/en/actions/writing-workflows/quickstart" rel="noopener noreferrer"&gt;GitHub Actions Docs&lt;/a&gt; &lt;a href="https://dev.to/ambujsahu81/create-a-simple-github-actions-workflow-347n"&gt;Dev.to Article&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;What is &lt;a href="https://github.com/actions/checkout" rel="noopener noreferrer"&gt;actions/checkout&lt;/a&gt; and &lt;a href="https://github.com/actions/setup-node" rel="noopener noreferrer"&gt;actions/setup-node&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Task
&lt;/h2&gt;

&lt;p&gt;Create a GitHub Actions workflow that runs whenever a PR is opened or updated, we want to check for three things in this workflow:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check if the &lt;strong&gt;linting&lt;/strong&gt; rules are followed.&lt;/li&gt;
&lt;li&gt;Check the &lt;strong&gt;formatting&lt;/strong&gt; of the code.&lt;/li&gt;
&lt;li&gt;Check all the &lt;strong&gt;test cases&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This helps maintain the quality of the source code and PR reviews, as the reviewer doesn't have to worry about whether this PR will break any existing(tested) functionality or cause lint and formatting issues.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a PR-Check Workflow
&lt;/h2&gt;

&lt;p&gt;Let's create a workflow file called &lt;code&gt;pr-check.yaml&lt;/code&gt; that triggers a pipeline whenever a PR is opened or updated against the &lt;code&gt;main&lt;/code&gt; branch.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Note:&lt;/strong&gt; For this article we will use the &lt;code&gt;ubuntu-latest&lt;/code&gt; runner but you can use whichever runner you want.  &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%2F9evz9d67q3lnv2lo10ir.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%2F9evz9d67q3lnv2lo10ir.png" alt="Define GitHub Actions Workflow" width="800" height="542"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now, let's check-out the repository, setup node, and install dependencies:&lt;br&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%2Fke06raxaxuwjd8j6bn71.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%2Fke06raxaxuwjd8j6bn71.png" alt="Setup project and install dependencies in a workflow" width="800" height="809"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the project has been setup and all the dependencies installed, let's run our PR-check scripts to check for lint, formatting, and tests:  &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%2Fmrbx3tc3038kkntqimb4.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%2Fmrbx3tc3038kkntqimb4.png" alt="First Workflow" width="800" height="957"&gt;&lt;/a&gt;&lt;br&gt;
Voila!, we have a nice workflow automation that will benefit our development process.   &lt;/p&gt;

&lt;p&gt;Or is it? &lt;/p&gt;

&lt;h3&gt;
  
  
  The Issues
&lt;/h3&gt;

&lt;p&gt;You see this automation looks fine at first, however, it has some issues:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All our tasks are crammed into one job.
&lt;/li&gt;
&lt;li&gt;On the GitHub Actions dashboard, the workflow diagram will look something like this:
&lt;a href="https://mermaid.live/edit#pako:eNo9jrEKwzAMRH8laGoh_QFvhY7N0g5dvAhbiU1iOygyaQn599oNVNPp3XHcBiZZAgX9lFbjkKW5P3Rsyl1PM1-MIzOedYQWAnFAb0t2qwEN4iiQBlWkRR41tAfPC3X4fnkrrrrCmXTcSwNmSc9PNKAqa4FTHhyoHqelfHm2KHTzODCGPyXrJXF3jPxt3b-5njwM" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNo9jrEKwzAMRH8laGoh_QFvhY7N0g5dvAhbiU1iOygyaQn599oNVNPp3XHcBiZZAgX9lFbjkKW5P3Rsyl1PM1-MIzOedYQWAnFAb0t2qwEN4iiQBlWkRR41tAfPC3X4fnkrrrrCmXTcSwNmSc9PNKAqa4FTHhyoHqelfHm2KHTzODCGPyXrJXF3jPxt3b-5njwM%3Ftype%3Dpng" alt="PR-Check GitHub Actions Diagram" width="107" height="70"&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;If one of our tasks fails, we have to look into the logs to determine which one failed. This might not look like an issue, but logs expire after some time, and if we have more tasks or long-running tasks, it can be hard to read logs. (I mean c'mon, don't pretend you love reading logs)
&lt;/li&gt;
&lt;li&gt;As a reviewer whenever there is a failing pipeline, you have to look into the logs and then tell the PR owner that 'this' check is failing in their PR. (Yeah, I don't like that either)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Better Approach
&lt;/h2&gt;

&lt;p&gt;One of our main issues is that all tasks are crammed into a single job, with no clear separation between them. So, let’s start by defining a separate job for each task. This will help keep things organized and make it easier to track each task individually!&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%2Fr4pmmk07c6xjuw1xw65m.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%2Fr4pmmk07c6xjuw1xw65m.png" alt="Modular workflow with each task in a separate job" width="800" height="1400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This solves all our issues! Each task runs in a separate job, so we don’t have to dig through logs to figure out where things went wrong. Plus, we get a nice diagram on the dashboard showing exactly which task failed. From there, we can dive right into the logs of the specific task to investigate further.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mermaid.live/edit#pako:eNo9j7EOgzAMRH8l8gQS_EC20o5laYcuWSxiSFSSVMFRWyH-vaEgPPnenU66GbqgCST0Y3h3BiOL6015ke9UjNZzKXYlQl3XQTRFH6LDgzc7PxdME5fKQwWOcsLq3DqvIQVsyJECmV-N8amg2niaqMXPw2o2q8sxkfJLbsDE4f71HciVVRBDGgzIHscpq_TSyHSxOER0ByVtOcR2m_NftfwAgEdGxw" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNo9j7EOgzAMRH8l8gQS_EC20o5laYcuWSxiSFSSVMFRWyH-vaEgPPnenU66GbqgCST0Y3h3BiOL6015ke9UjNZzKXYlQl3XQTRFH6LDgzc7PxdME5fKQwWOcsLq3DqvIQVsyJECmV-N8amg2niaqMXPw2o2q8sxkfJLbsDE4f71HciVVRBDGgzIHscpq_TSyHSxOER0ByVtOcR2m_NftfwAgEdGxw%3Ftype%3Dpng" alt="PR-Check GitHub Actions Diagram, with each task in separate job" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, it has a huge issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Issue
&lt;/h3&gt;

&lt;p&gt;Since each job runs in an isolated environment, it needs to make separate network calls for repeated actions, such as &lt;code&gt;actions/checkout&lt;/code&gt;, &lt;code&gt;actions/setup-node&lt;/code&gt;, and &lt;code&gt;Installing Dependencies&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching
&lt;/h3&gt;

&lt;p&gt;The extra network calls issue can be solved by caching the actions and their output.&lt;/p&gt;

&lt;h4&gt;
  
  
  actions/checkout
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;actions/checkout&lt;/code&gt; is globally cached by GitHub Actions and doesn't require any network calls to setup, it also automatically caches the checked-out repository for the whole workflow run and will only need to make a network call to check-out the repository during the first job run and then it uses the workflow cache to check-out the repository in subsequent jobs.&lt;/p&gt;

&lt;h4&gt;
  
  
  actions/setup-node
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;actions/setup-node&lt;/code&gt; is also globally cached by GitHub Actions and doesn't require any network calls to setup. It will first check the local cache to install the specified version of Node.js and only when it can't find that version in the cache, it will fall back to downloading the specified version and cache it for the workflow run.  &lt;/p&gt;

&lt;p&gt;GitHub Actions hosted runners provide locally cached Node.js versions based on the &lt;a href="https://github.com/actions/runner-images" rel="noopener noreferrer"&gt;Runner Image&lt;/a&gt;, you can also access this cache in your &lt;a href="https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners" rel="noopener noreferrer"&gt;self-hosted runner&lt;/a&gt; if it has access to &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;github.com&lt;/a&gt; or you can setup &lt;a href="https://docs.github.com/en/enterprise-server@3.14/admin/managing-github-actions-for-your-enterprise/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access" rel="noopener noreferrer"&gt;tool cache on self-hosted runners&lt;/a&gt; to cache the required Node.js versions locally.&lt;/p&gt;

&lt;h4&gt;
  
  
  Installing Dependencies
&lt;/h4&gt;

&lt;p&gt;To install dependencies, we need to download packages from the NPM registry. Since GitHub can't cache every package available on NPM, each job run has to download these packages directly from NPM. This results in network calls for each job, which not only increases the execution time for each job (and subsequently the overall workflow runtime) but also eats the runner quota—especially for private repositories.&lt;/p&gt;

&lt;p&gt;Yikes! That's a bummer, isn't it?&lt;/p&gt;

&lt;p&gt;We can use another amazing action provided by GitHub, &lt;a href="https://github.com/actions/cache" rel="noopener noreferrer"&gt;&lt;code&gt;actions/cache&lt;/code&gt;&lt;/a&gt; to cache our dependencies from our first job run and use that for subsequent jobs.  &lt;/p&gt;

&lt;p&gt;However, we have something even better. &lt;code&gt;actions/setup-node&lt;/code&gt; has &lt;a href="https://github.com/actions/setup-node?tab=readme-ov-file#caching-global-packages-data" rel="noopener noreferrer"&gt;built-in support&lt;/a&gt; for caching global packages data and restoring dependencies from the cache (if available) using &lt;code&gt;actions/cache&lt;/code&gt; under the hood. All we have to do is use the optional &lt;code&gt;cache&lt;/code&gt; option and pass in the name of the package manager (supported package managers are &lt;code&gt;npm&lt;/code&gt;, &lt;code&gt;yarn&lt;/code&gt;, and &lt;code&gt;pnpm&lt;/code&gt; (v6.10+)).  &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%2Fegp59ibcwx39v632wtrg.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%2Fegp59ibcwx39v632wtrg.png" alt="How to setup cache in actions/setup-node" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It gets even better, &lt;code&gt;actions/setup-node&lt;/code&gt; defaults to searching for the dependency file (package-lock.json, npm-shrinkwrap.json, or yarn.lock) in the repository root, and uses its hash as a part of the cache key, which means any subsequent workflow runs will use the same global packages cache if the lock file is unchanged (i.e. no changes in the dependencies) or till the &lt;a href="https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy" rel="noopener noreferrer"&gt;cache is alive&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Better Workflow
&lt;/h3&gt;

&lt;p&gt;Now, let’s put our caching knowledge into the workflow by creating a separate job for each task(check).&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%2Fipsc0gy5m4xxh6o5gnn6.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%2Fipsc0gy5m4xxh6o5gnn6.png" alt="Final workflow with modular jobs for each task and caching" width="800" height="1473"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Using the &lt;code&gt;actions&lt;/code&gt;, &lt;code&gt;modularity&lt;/code&gt;, and &lt;code&gt;caching&lt;/code&gt; features in GitHub Actions, we developed an effective and efficient workflow to automate our &lt;code&gt;pr-checks&lt;/code&gt;. Similarly, we can utilize these features in other CI/CD operations and contribute towards improving project workflow.  &lt;/p&gt;

&lt;p&gt;If you enjoyed this article and want to connect, feel free to reach out on &lt;a href="https://www.linkedin.com/in/idris-gadi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://x.com/igadii_X" rel="noopener noreferrer"&gt;X/Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>node</category>
      <category>github</category>
    </item>
    <item>
      <title>How TypeScript Makes React Better: Smoother Developer Experience, Fewer Bugs (With a useState Example)</title>
      <dc:creator>Idris Gadi</dc:creator>
      <pubDate>Sun, 27 Oct 2024 15:51:53 +0000</pubDate>
      <link>https://dev.to/igadii/how-typescript-makes-react-better-smoother-developer-experience-fewer-bugs-with-a-usestate-example-4loh</link>
      <guid>https://dev.to/igadii/how-typescript-makes-react-better-smoother-developer-experience-fewer-bugs-with-a-usestate-example-4loh</guid>
      <description>&lt;p&gt;Let's start with a scenario and a task associated with it.&lt;/p&gt;

&lt;p&gt;We have a messaging application with a status bar that shows the user's current status and allows them to update it. We have to add a dropdown from which the user can change their status and use &lt;code&gt;useState()&lt;/code&gt; to show and update the user's current status in the UI.  &lt;/p&gt;

&lt;p&gt;For simplicity, we will only focus on the &lt;code&gt;useState&lt;/code&gt; implementation in this article, and by the end of the article, you will understand how even for a simple example TypeScript is a much more powerful option.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Task
&lt;/h2&gt;

&lt;p&gt;We have to define a &lt;code&gt;useState()&lt;/code&gt; that stores and updates &lt;code&gt;userStatus&lt;/code&gt; and is initialized with one of the five possible status options (let's say &lt;strong&gt;active&lt;/strong&gt;).    &lt;/p&gt;

&lt;p&gt;All the possible options are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Active (active)&lt;/li&gt;
&lt;li&gt;Away (away)&lt;/li&gt;
&lt;li&gt;Do Not Disturb (dnd)&lt;/li&gt;
&lt;li&gt;On Leave (leave)&lt;/li&gt;
&lt;li&gt;Out Of Office (OOO)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  JSX/JS
&lt;/h2&gt;

&lt;p&gt;This is a very straightforward task, right? All we have to do is define a &lt;code&gt;useState&lt;/code&gt; and initialize it to &lt;strong&gt;active&lt;/strong&gt; and then use the &lt;code&gt;set&lt;/code&gt; function to update the status and we are done.&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%2F28knve9flzflf465rhxa.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%2F28knve9flzflf465rhxa.png" alt="Screenshot of useState definition in JS" width="520" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But wait! What happens when someone is reviewing my code or visits this piece of code later (say after 1 week, 2 weeks, 1 month, 6 months, or whatever), how will they know what are all the possible/valid options?&lt;/p&gt;

&lt;p&gt;Ahh! Yes, we can add a comment next to the &lt;code&gt;useState&lt;/code&gt; to let them know that these are all the possible options.&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%2Ff6zk4n7tfcdqm1b9dian.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%2Ff6zk4n7tfcdqm1b9dian.png" alt="Screenshot of useState definition in JS with possible options mentioned in the comments" width="566" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, this isn't a good solution, right? So, how can we improve it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Object Lookup
&lt;/h3&gt;

&lt;p&gt;Object lookup is a really nice solution to our problem. So, let's start with defining an object lookup called &lt;code&gt;UserStatus&lt;/code&gt; and use it to set our &lt;code&gt;userStatus&lt;/code&gt; value.&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%2Fhljea9yihwvgi38ymiqg.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%2Fhljea9yihwvgi38ymiqg.png" alt="Screenshot of UserStatus object lookup definition" width="407" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's update our &lt;code&gt;useState&lt;/code&gt; definition.&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%2F084uft416at9uszer1tj.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%2F084uft416at9uszer1tj.png" alt="Screenshot of userStatus useState initialized with UserStatus object lookup" width="601" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's try to update the status.&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%2F6ttam5ng8qaw5o1664as.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%2F6ttam5ng8qaw5o1664as.png" alt="Screenshot of using setUserStatus with object lookup and getting autocomplete" width="717" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ohh! Look at that, now we get autocomplete in our editor and can check all the possible/valid values of &lt;code&gt;userStatus&lt;/code&gt; by looking at the definition of &lt;code&gt;UserStatus&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Issues with Object Lookup
&lt;/h3&gt;

&lt;p&gt;Even though the object lookup method has seemingly solved our problem and is definitely a far better solution than just adding comments, it still has two major issues:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For anyone visiting our piece of code later, they have to know that we are using an object lookup to set our state. This might seem trivial but imagine as our component grows and becomes more complex, then it becomes very easy for someone to be unaware of our implementation.&lt;/li&gt;
&lt;li&gt;It still doesn't prevent anyone from setting any random value to our state, even when they are aware of the object lookup.
 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, how can we solve these issues?&lt;br&gt;
Answer: &lt;strong&gt;Typescript&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TSX/TS
&lt;/h2&gt;

&lt;p&gt;Let's start again with our solution, but this time in a &lt;code&gt;.tsx&lt;/code&gt; or a Typescript file. We can start by defining a &lt;code&gt;useState()&lt;/code&gt; function and initializing it with the value: &lt;strong&gt;active&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3m9ghq2a831r8ab8qsr.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%2Fo3m9ghq2a831r8ab8qsr.png" alt="Screenshot of useState definition in TS" width="512" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nothing seems different right now, but it is. Let's update the &lt;code&gt;userStatus&lt;/code&gt; value.&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%2Fcv9ht3jevad6bqxqmnef.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%2Fcv9ht3jevad6bqxqmnef.png" alt="Screenshot of using setUserStatus function with some string valid/invalid and other type of values" width="409" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahh! As you can see it is giving us that dreaded red squiggly error line around some set functions but not on ones where we are setting a &lt;code&gt;string&lt;/code&gt; value. This is because Typescript is inferring the type of our state from its initial value (i.e. type &lt;code&gt;string&lt;/code&gt;).  &lt;/p&gt;

&lt;p&gt;Yes, this will prevent us from setting any non-string values to our &lt;code&gt;userStatus&lt;/code&gt; state, but it still doesn't prevent us from setting any random string value and we still have to use the object lookup for documenting all the possible options, you may ask.&lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;Let's do some "One Stone, Two Birds".&lt;/p&gt;

&lt;h3&gt;
  
  
  Explicit Types and Generics
&lt;/h3&gt;

&lt;p&gt;In Typescript we can create &lt;strong&gt;custom types&lt;/strong&gt; and it also has support for &lt;strong&gt;generics&lt;/strong&gt; which can be used in React for its hook definitions, in our case the &lt;code&gt;useState()&lt;/code&gt; hook.&lt;br&gt;&lt;br&gt;
Let's create a new &lt;code&gt;UserStatus&lt;/code&gt; type in our React component.  &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%2Fnw4j5adis7mv300d16sy.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%2Fnw4j5adis7mv300d16sy.png" alt="UserStatus type definition" width="600" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's use this type in our &lt;code&gt;useState&lt;/code&gt; definition.  &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%2F0yj5lbsj76z4067pfgxb.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%2F0yj5lbsj76z4067pfgxb.png" alt="Screenshot of useState definition in TS with custom type" width="672" height="95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Till now, everything looks similar to how we were doing it in the object lookup method, but the magic of Typescript is when we start using our set function and the state value.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Getting the type definition of &lt;code&gt;userStatus&lt;/code&gt;.&lt;br&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%2F23o0571b0icyc2i6l9gl.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%2F23o0571b0icyc2i6l9gl.png" alt="Screenshot of hint box in editor showing the type of the state" width="422" height="128"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Autocomplete for the &lt;code&gt;setUserStatus&lt;/code&gt; function.&lt;br&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%2F7mhfl3zje33t2qx5jspo.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%2F7mhfl3zje33t2qx5jspo.png" alt="Screenshot of getting autocomplete for the valid values in setState function" width="637" height="186"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Getting proper validation for valid and invalid values.&lt;br&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%2F9pa0p383quo0bpuc1out.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%2F9pa0p383quo0bpuc1out.png" alt="Screenshot of the editor showing that only valid values are accepted and all the invalid values are getting errors" width="377" height="163"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Look at that,  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We can get the documentation of all the valid values by simply hovering over the &lt;code&gt;userStatus&lt;/code&gt; and looking up its type definition.&lt;/li&gt;
&lt;li&gt;However, we don't need to look at the type definition of our state value when using the set function, as it automatically gives us the autocomplete for all the valid options.&lt;/li&gt;
&lt;li&gt;Now it not only gives us the error when setting a non-string value, but it also gives us the error for using invalid string values (i.e. it will always give errors for invalid inputs).&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;By now, you probably have got a good feel for how TypeScript can really enhance our development experience. We have only scratched the surface with a simple example here, but just think about the real-world applications we’re building, using TypeScript could mean way fewer bugs and a way better developer experience overall.  &lt;/p&gt;

&lt;p&gt;I hope this article encourages you to start using Typescript in all your React applications and build awesome web experiences.  &lt;/p&gt;

&lt;p&gt;If you liked this article and would like to connect, then you can connect with me on &lt;a href="https://www.linkedin.com/in/idris-gadi/" rel="noopener noreferrer"&gt;Linked&lt;/a&gt; and &lt;a href="https://x.com/igadii_X" rel="noopener noreferrer"&gt;X/Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Beyond Basics: Handling Numeric Inputs Like a Pro with `&lt;input type="number"&gt;`</title>
      <dc:creator>Idris Gadi</dc:creator>
      <pubDate>Mon, 09 Sep 2024 07:40:16 +0000</pubDate>
      <link>https://dev.to/igadii/beyond-basics-handling-numeric-inputs-like-a-pro-with--40bf</link>
      <guid>https://dev.to/igadii/beyond-basics-handling-numeric-inputs-like-a-pro-with--40bf</guid>
      <description>&lt;h2&gt;
  
  
  What is &lt;code&gt;&amp;lt;input type="number"&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number" rel="noopener noreferrer"&gt;MDN Docs Definition&lt;/a&gt;: &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; elements of type number are used to let the user enter a number. They include built-in validation to reject non-numerical entries.&lt;br&gt;&lt;br&gt;
So basically, it is a feature for enhancing User Experience on our crappy websites and web apps. While it is a nice feature for simplifying numeric inputs, it has a couple of behaviors that might not be obvious at first but we should be aware of as a web developer. &lt;/p&gt;

&lt;p&gt;These behaviors are related to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Virtual Keyboard&lt;/li&gt;
&lt;li&gt;Scientific Notations&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Virtual Keyboard
&lt;/h2&gt;

&lt;p&gt;A virtual keyboard is a keyboard that appears on your screen, usually in touch input devices like mobile phones, tablets/ipads and some assistive technologies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"numeric-input"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just using the &lt;code&gt;type="number"&lt;/code&gt; might seem all right at first, but it has an issue when using a virtual keyboard. It might open a full-key keyboard instead of a numeric keyboard, which can hurt user experience and input accuracy.&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%2Ftcz9zi2hsb3yllngxjgz.gif" 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%2Ftcz9zi2hsb3yllngxjgz.gif" alt="A Gif demonstrating that input number can lead to full-key keyboard" width="319" height="689"&gt;&lt;/a&gt;     &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution &lt;code&gt;inputmode&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;While the virtual keyboard issue might not occur on newer OS and browser versions, it is still a good idea to use the &lt;code&gt;inputmode&lt;/code&gt; attribute as it hints at the type of data that might be entered by the user while editing the element or its contents. &lt;br&gt;
This allows browsers to display an appropriate virtual keyboard for all versions and devices, improving the application's overall user experience (UX).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;inputmode&lt;/code&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode#values" rel="noopener noreferrer"&gt;can have many values&lt;/a&gt;, but for our use case with numeric inputs we should use one of these two values:&lt;br&gt;
1.&lt;strong&gt;numeric&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"numeric-input"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="na"&gt;inputmode=&lt;/span&gt;&lt;span class="s"&gt;"numeric"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The input type number accepts any rational value. If you are not accepting fractional values and only accepting whole numbers, using a &lt;code&gt;numeric&lt;/code&gt; value should be preferred for such scenarios.&lt;/p&gt;

&lt;p&gt;2.&lt;strong&gt;decimal&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"numeric-input"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"number"&lt;/span&gt; &lt;span class="na"&gt;inputmode=&lt;/span&gt;&lt;span class="s"&gt;"decimal"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are accepting fractional numbers, use &lt;code&gt;decimal&lt;/code&gt; value as it will show a virtual keyboard containing the digits and decimal separator for the user's locale. &lt;/p&gt;

&lt;p&gt;Always prefer using &lt;code&gt;decimal&lt;/code&gt; value in your input unless you are not accepting fractional values.  &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%2Fxjbpmm6x44vc1sqa4dd1.gif" 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%2Fxjbpmm6x44vc1sqa4dd1.gif" alt="A Gif demonstrating input type number with input mode of decimal" width="320" height="687"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Scientific Notations
&lt;/h2&gt;

&lt;p&gt;Many of us might have forgotten or not know that &lt;code&gt;e&lt;/code&gt; or &lt;code&gt;E&lt;/code&gt; are valid numeric values in scientific notations.&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%2Fi78o2lqvnigi2086gnnm.gif" 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%2Fi78o2lqvnigi2086gnnm.gif" alt="what meme" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, &lt;code&gt;e&lt;/code&gt; or &lt;code&gt;E&lt;/code&gt; means &lt;strong&gt;"exponent of ten"&lt;/strong&gt; in scientific notations, and is used to represent very large or small values. e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1e5 = 100000 
     or 
1e-5 = 0.00001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The HTML input type number was designed with flexibility in mind, and it supports this scientific notation, allowing for the entry of exponents (e.g., 1e5). While this is not an issue in itself and can be useful in some contexts, it can become problematic when the input should only consist of basic numbers.&lt;/p&gt;

&lt;p&gt;There are two ways to restrict the input to only numbers and not allow the scientific notations.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using Regex 🤮 pattern.&lt;/li&gt;
&lt;li&gt;Using Javascript (my preferred method).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Preventing Default Behaviour Using Javascript
&lt;/h3&gt;

&lt;p&gt;In most scenarios, I don't want the users to enter the 'e' or 'E' notations, as they aren't needed, and allowing them can cause some unexpected issues.&lt;/p&gt;

&lt;p&gt;There are many ways of achieving this, but my favorite method is to prevent the 'e' or 'E' key from being registered. We can achieve this using the &lt;code&gt;keydown&lt;/code&gt; event and &lt;code&gt;preventDefault&lt;/code&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="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keydown&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;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;e&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;E&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// you can also add "+" and "-" if you want to prevent them from being registered.&lt;/span&gt;
      &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&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;I particularly like this method because of three reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It provides a clear message to anyone reading our code later that we don't want to register the &lt;strong&gt;e&lt;/strong&gt; or &lt;strong&gt;E&lt;/strong&gt; keys.
&lt;/li&gt;
&lt;li&gt;It also allows for a better UX because instead of changing the values we are not registering the key itself.
&lt;/li&gt;
&lt;li&gt;The type of &lt;strong&gt;keydown&lt;/strong&gt; event is &lt;strong&gt;KeyboardEvent&lt;/strong&gt; which gives us direct access to the key values improving the overall DX of the solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Not All Numeric Input Needs to be Input Type Number
&lt;/h2&gt;

&lt;p&gt;Sometimes we can instinctively reach for an input type number if we see an input requirement that accepts numeric input but sometimes input type number is not the right solution for such scenarios. &lt;/p&gt;

&lt;p&gt;A few examples of such scenarios are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Credit Card/Debit Card:&lt;/strong&gt; When we have an input field for Credit/Debit Card, instead of using input type number it is better to use input type text with input mode of numeric and validation using your preferred method, as a credit card can have leading zero values and some browsers might not allow that, also we might want to add some card specific validations or allow spacing between a group of four numbers (as it is printed on the card).     &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Postal Code:&lt;/strong&gt; While most countries have numeric postal codes, some countries like Canada could have alphanumeric codes, it is important to use solutions according to your need, it could be of input type number or input type text.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mobile Numbers:&lt;/strong&gt; You should always use the input type of &lt;code&gt;input="tel"&lt;/code&gt; with a regex pattern suitable for your use case.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Since modern HTML provides some really nice utilities, some things might feel very trivial to implement like &lt;code&gt;input type number&lt;/code&gt;, however as developers, we should always pay attention to these utilities and how we can utilize them to create even better user experiences.&lt;/p&gt;

&lt;p&gt;If you liked this article please leave a reaction and if you disliked something you can leave your feedback in the comments.&lt;/p&gt;

&lt;p&gt;I like to connect and talk with people about tech and the events surrounding it. You can connect with me on &lt;a href="https://x.com/igadii_X" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/idris-gadi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;You can also follow me on &lt;a href="https://dev.to/igadii"&gt;Dev.to&lt;/a&gt; to get a notification whenever I publish a new article.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>html</category>
      <category>learning</category>
    </item>
    <item>
      <title>Why is Math.min() Greater-Than Math.max() in JavaScript</title>
      <dc:creator>Idris Gadi</dc:creator>
      <pubDate>Sat, 31 Aug 2024 13:51:15 +0000</pubDate>
      <link>https://dev.to/igadii/why-mathmin-mathmax-in-javascript-makes-complete-sense-as-it-is-164p</link>
      <guid>https://dev.to/igadii/why-mathmin-mathmax-in-javascript-makes-complete-sense-as-it-is-164p</guid>
      <description>&lt;h2&gt;
  
  
  Expression Breakdown
&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%2Fj4vtyzrp6vieg1fxk163.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%2Fj4vtyzrp6vieg1fxk163.png" alt="Image showing Math.min() &amp;gt; Math.max() expression and describing its three parts" width="599" height="212"&gt;&lt;/a&gt;&lt;br&gt;
Let's start by breaking down the expression. It essentially has three parts, two static methods, and a greater than operator between them.&lt;/p&gt;

&lt;p&gt;&lt;a href="//#the-expression-math.min--math.max"&gt;I don't want to read through the article, give me TLDR;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Greater than operator &lt;code&gt;&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The greater-than (&lt;code&gt;&amp;gt;&lt;/code&gt;) operator returns &lt;code&gt;true&lt;/code&gt; if the left operand is greater than the right operand and &lt;code&gt;false&lt;/code&gt; otherwise. This is very straightforward.&lt;br&gt;&lt;br&gt;
Now, let's look at the two method calls.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Math.min()&lt;/code&gt; and &lt;code&gt;Math.max()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Math.min()&lt;/code&gt; and &lt;code&gt;Math.max()&lt;/code&gt; are static methods of the &lt;code&gt;Math&lt;/code&gt; class that takes in a set of numbers as input arguments and returns the smallest or the largest number from the set respectively. &lt;/p&gt;

&lt;p&gt;Let's look at some examples.&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="cm"&gt;/* Math.min() */&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&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="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: 1&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: -10&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: -5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Math.max() */&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&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="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: 9&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: -3&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What If We Pass Only One Argument
&lt;/h2&gt;

&lt;p&gt;In the examples, we saw that &lt;code&gt;min()&lt;/code&gt; and &lt;code&gt;max()&lt;/code&gt; methods are basically comparing the values present in the set and returning the smallest or the largest value respectively. Now, what if we pass a set with only a single 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="cm"&gt;/* Math.min() */&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: 7&lt;/span&gt;
&lt;span class="cm"&gt;/* Math.max() */&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both method returns the input value, that is because they have an implicit argument that they use in the comparison set, and when only a single value is passed in that set, it compares that value against the implicit argument.  &lt;/p&gt;

&lt;h3&gt;
  
  
  What Are These Implicit Arguments
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;min()&lt;/code&gt; and &lt;code&gt;max()&lt;/code&gt; both use different implicit arguments.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;Math.min()&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;As &lt;code&gt;min()&lt;/code&gt; returns the smallest number from the input set, it uses the largest number as the implicit argument. That is the &lt;code&gt;Infinity&lt;/code&gt;, as no number can be larger than the infinity, a comparison against it will always return the other value.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;Math.max()&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Similarly &lt;code&gt;max()&lt;/code&gt; returns the largest number from the input set, it uses the smallest number as the implicit argument. That is the &lt;code&gt;-Infinity&lt;/code&gt;, as no number can be smaller than the negative infinity, a comparison against it will always return the other value.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Expression &lt;code&gt;Math.min() &amp;gt; Math.max()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;We saw that if we pass only a single value in the input set, both the &lt;code&gt;min()&lt;/code&gt; and &lt;code&gt;max()&lt;/code&gt; methods will return the value and why it does that.&lt;br&gt;&lt;br&gt;
Now, what if we don't pass any input arguments?&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="cm"&gt;/* Math.min() */&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Output: Infinity&lt;/span&gt;
&lt;span class="cm"&gt;/* Math.max() */&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Output: -Infinity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both methods returns their implicit arguments that is, &lt;code&gt;Infinity&lt;/code&gt; and &lt;code&gt;-Infinity&lt;/code&gt; respectively.&lt;/p&gt;

&lt;p&gt;Now, we know the return values of &lt;code&gt;Math.min()&lt;/code&gt; and &lt;code&gt;Math.max()&lt;/code&gt;, and we also know that the greater-than &lt;code&gt;&amp;gt;&lt;/code&gt; operator compares the values and not the function expression.  &lt;/p&gt;

&lt;p&gt;So what if we compare the return values of &lt;code&gt;Math.min()&lt;/code&gt; and &lt;code&gt;Math.max()&lt;/code&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="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="kc"&gt;Infinity&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Output: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Output: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hence, why &lt;strong&gt;Math.min() &amp;gt; Math.max()&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;It is not only true for the &lt;code&gt;Math.min() &amp;gt; Math.max()&lt;/code&gt; expression, but any expression where the return value of &lt;code&gt;min()&lt;/code&gt; is greater than the value of &lt;code&gt;max()&lt;/code&gt;. e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&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="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: true&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: true&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Output: false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Sometimes we fall victim to the logical fallacies and &lt;code&gt;Math.min() &amp;gt; Math.max()&lt;/code&gt; is a nice example for that, it doesn't feel weird when we have sets of numbers where the return value of &lt;code&gt;min()&lt;/code&gt; is greater than the return value of &lt;code&gt;max()&lt;/code&gt; as in the example above.  &lt;/p&gt;

&lt;p&gt;However, when we see an empty set of arguments, we start comparing the meaning of &lt;code&gt;min()&lt;/code&gt; (minimum) and &lt;code&gt;max()&lt;/code&gt; (maximum) instead of comparing their return values and it leads to falling for the logical fallacy that &lt;code&gt;Math.min()&lt;/code&gt; shouldn't be greater than &lt;code&gt;Math.max()&lt;/code&gt; and hence it should be a quirk of Javascript, but as we saw in this article, it makes complete sense why it is &lt;code&gt;true&lt;/code&gt; and why it would be absurd if it wasn't.  &lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article and learned something new or refreshed your knowledge and I also hope that it makes you like Javascript a little bit more :).  &lt;/p&gt;

&lt;p&gt;I like to connect and talk with people about tech in general and the events surrounding it. You can connect with me on &lt;a href="https://x.com/igadii_X" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/idris-gadi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. You can also follow me on &lt;a href="https://dev.to/igadii"&gt;dev.to&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>learning</category>
    </item>
    <item>
      <title>Why and How to Migrate Your React App from CRA to Vite</title>
      <dc:creator>Idris Gadi</dc:creator>
      <pubDate>Mon, 10 Jun 2024 07:19:59 +0000</pubDate>
      <link>https://dev.to/igadii/why-and-how-to-migrate-your-react-app-from-cra-to-vite-2ni6</link>
      <guid>https://dev.to/igadii/why-and-how-to-migrate-your-react-app-from-cra-to-vite-2ni6</guid>
      <description>&lt;h3&gt;
  
  
  Updates
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;February 2025&lt;/strong&gt;: CRA is officially on a path for full deprecation, there is already a deprecation warning added to the project's readme and open PRs to deprecate the docs website and the CLI installation.&lt;br&gt;&lt;br&gt;
You can track the status of this issue: &lt;a href="https://github.com/facebook/create-react-app/issues/17004" rel="noopener noreferrer"&gt;Umbrella: CRA breaks with React 19, and CRA needs deprecation notices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw38p3kbaexdzdclmg21w.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%2Fw38p3kbaexdzdclmg21w.png" alt="CRA Readme deprecation warning" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;As of the time of writing this article (10/06/2024), CRA has been effectively semi-dead for the past two years. It has not received any commits since last year, or any important ones for the past two years in &lt;a href="https://github.com/facebook/create-react-app/commits/main/" rel="noopener noreferrer"&gt;CRA commit history&lt;/a&gt;. Issues have been piling up, and none are being addressed in &lt;a href="https://github.com/facebook/create-react-app/issues" rel="noopener noreferrer"&gt;CRA issues&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91pxzyuqsmekl0u6gmvn.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%2F91pxzyuqsmekl0u6gmvn.png" alt="screenshot of CRA commit history showcasing that it has not received any commits for the past two years" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So why is it in a semi-dead state but not dead? The React team has not deprecated it. If it's not deprecated, then it might have reached a certain level of maturity and might not need any new changes. Thus, it is not in a semi-dead state but has reached a certain level of maturity.&lt;/p&gt;

&lt;p&gt;Here is the tricky situation and that's why CRA is in a semi-dead state, it has not been deprecated but isn't receiving any updates not even security updates, along with the new &lt;a href="https://react.dev/learn/start-a-new-react-project" rel="noopener noreferrer"&gt;React.dev&lt;/a&gt; documentation doesn't mention CRA but suggests using React meta-frameworks like &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next&lt;/a&gt; and &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Remix&lt;/a&gt; for new projects. You can read more about React's reasoning for it in this &lt;a href="https://github.com/reactjs/react.dev/pull/5487#issuecomment-1409720741" rel="noopener noreferrer"&gt;GitHub issue discussion&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So React suggests using meta-frameworks for new projects, which means it should be fine to use CRA in the existing projects. you may ask. The issue with it is that it lacks many of the modern build tools features that we need in production applications and it might not be possible or you might not want to migrate to a meta-framework, which means either you have to eject out of CRA and maintain your webpack configuration or you can use another brilliant frontend build tool call Vite.&lt;/p&gt;
&lt;h2&gt;
  
  
  Vite
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; is a modern frontend build tool created by &lt;a href="https://x.com/youyuxi" rel="noopener noreferrer"&gt;Evan You&lt;/a&gt; (creator of &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt;). Vite is framework agnostic and works on a plugin-based approach.&lt;/p&gt;

&lt;p&gt;For this article, we will specifically focus on migrating a React App from CRA to Vite.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Vite?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Vite's plugin-based approach allows us to configure the project that best suits our use case by exposing low-level APIs as much as possible without needing to configure the underlying bundler.&lt;/li&gt;
&lt;li&gt;Vite is not a bundler but a frontend tool that intelligently uses &lt;a href="https://esbuild.github.io/" rel="noopener noreferrer"&gt;ESBuild&lt;/a&gt; and &lt;a href="https://rollupjs.org/" rel="noopener noreferrer"&gt;Rollup&lt;/a&gt; for their best use cases.&lt;/li&gt;
&lt;li&gt;Vite servers Native ESM code in the dev server mode for better start/reload times and HMR (Hot Module Replacement).&lt;/li&gt;
&lt;li&gt;Using ESBuilt, Vite creates a highly optimized prod bundle with support for better code splitting and tree shaking.&lt;/li&gt;
&lt;li&gt;Using plugins for configuring the project means that we can pick and choose what we want to use for certain things.&lt;/li&gt;
&lt;li&gt;We can effectively create our meta-framework using Vite, as it even supports things like SSR and SSG.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are many more benefits of using Vite as discussed by the Vite team here &lt;a href="https://vitejs.dev/guide/why.html" rel="noopener noreferrer"&gt;Why Vite?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's see how to migrate our existing CRA project to Vite.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE:&lt;br&gt;
 I will be providing overview implementations and pseudo code and commands in this article since my aim is not to give you a template but to guide you toward migrating your app that fits your needs. I will provide the necessary and important references throughout the article for your help.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Install Vite
&lt;/h3&gt;

&lt;p&gt;We can start by installing Vite in our current project.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install React Plugin
&lt;/h3&gt;

&lt;p&gt;As Vite works on a plugin-based approach, we will have to install one of the two official React plugins. You can read more about them and choose the one that suits your needs from here &lt;a href="https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react" rel="noopener noreferrer"&gt;@vitejs/plugin-react&lt;/a&gt; and &lt;a href="https://github.com/vitejs/vite-plugin-react-swc" rel="noopener noreferrer"&gt;@vitejs/plugin-react-swc&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  index.html
&lt;/h3&gt;

&lt;p&gt;During development, Vite is a server and it uses index.html as the entry point. Therefore we need to make a few changes to the index.html file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move index.html file to the root of the project.&lt;/li&gt;
&lt;li&gt;URLs inside index.html are automatically rebased so there's no need for special %PUBLIC_URL% placeholders and they can be removed.&lt;/li&gt;
&lt;li&gt;Add below script tag that allows it to reference the Javascript source code. (preferably at the end of the body tag, as that's where a fresh Vite project puts it)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/src/index.tsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Config file
&lt;/h3&gt;

&lt;p&gt;Next, we will have to create a &lt;code&gt;vite.config.js&lt;/code&gt; or &lt;code&gt;vite.config.ts&lt;/code&gt; file at the root of the project based on whether if its a Javascript or a Typescript project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&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;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&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;You can read more about all the configuration options at &lt;a href="https://vitejs.dev/config/" rel="noopener noreferrer"&gt;Config&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Typescript
&lt;/h3&gt;

&lt;p&gt;To resolve imports using TypeScript's path mapping you will have to use one of the community plugins for Vite. You can read more about it here &lt;a href="https://github.com/aleclarson/vite-tsconfig-paths" rel="noopener noreferrer"&gt;vite-tsconfig-paths&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment Variables
&lt;/h3&gt;

&lt;p&gt;Vite exposes env variables on the special &lt;code&gt;import.meta.env&lt;/code&gt; object, which are statically replaced at build time. To prevent accidentally leaking env variables to the client, only variables prefixed with &lt;code&gt;VITE_&lt;/code&gt; are exposed.&lt;/p&gt;

&lt;p&gt;Therefore, we will have to replace all the &lt;code&gt;process.env.&lt;/code&gt; with &lt;code&gt;import.meta.env.&lt;/code&gt; and replace the &lt;code&gt;REACT_APP_&lt;/code&gt; prefix with &lt;code&gt;VITE_&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# CRA env variable
REACT_APP_MY_ENV = 'some value'
process.env.REACT_APP_MY_ENV

# Vite env variable
VITE_MY_ENV = 'some value'
import.meta.env.VITE_MY_ENV 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SVGs
&lt;/h3&gt;

&lt;p&gt;To use SVGs and SVGs as a React component in our Vite project, we will have to use another awesome community plugin called &lt;code&gt;svgr()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can check out &lt;a href="https://github.com/pd4d10/vite-plugin-svgr" rel="noopener noreferrer"&gt;vite-plugin-svgr&lt;/a&gt; to learn more about how to install and use &lt;code&gt;svgr()&lt;/code&gt; and all the configuration options that it exposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  JSX in JS
&lt;/h3&gt;

&lt;p&gt;By default, Vite will not resolve any JSX file with &lt;code&gt;.js&lt;/code&gt; extension, even though there are workarounds to resolve this, it would be better to migrate all the JSX files with &lt;code&gt;.js&lt;/code&gt; or &lt;code&gt;.ts&lt;/code&gt; extension to &lt;code&gt;.jsx&lt;/code&gt; or &lt;code&gt;.tsx&lt;/code&gt; as this is the official recommendation from the Vite team.&lt;/p&gt;

&lt;p&gt;To learn more about the reasoning behind this decision you can read this &lt;a href="https://x.com/youyuxi/status/1362050255009816577" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt; thread by Evan You.&lt;/p&gt;

&lt;h3&gt;
  
  
  Browserslist
&lt;/h3&gt;

&lt;p&gt;For a production build, you are likely using &lt;a href="https://github.com/browserslist/browserslist" rel="noopener noreferrer"&gt;Browserslist&lt;/a&gt;, by default Vite targets browsers that support &lt;a href="https://caniuse.com/es6-module" rel="noopener noreferrer"&gt;native ES Modules&lt;/a&gt;, &lt;a href="https://caniuse.com/es6-module-dynamic-import" rel="noopener noreferrer"&gt;native ESM dynamic import&lt;/a&gt;, and &lt;a href="https://caniuse.com/mdn-javascript_operators_import_meta" rel="noopener noreferrer"&gt;import.meta&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In Vite, legacy browsers can be supported via the official &lt;a href="https://github.com/vitejs/vite/tree/main/packages/plugin-legacy" rel="noopener noreferrer"&gt;@vitejs/plugin-legacy&lt;/a&gt; plugin, it also provides Browselist-like configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build File
&lt;/h3&gt;

&lt;p&gt;For the production build, Vite creates a &lt;code&gt;dist&lt;/code&gt; directory while CRA creates a &lt;code&gt;build&lt;/code&gt; directory, if you have a CI/CD pipeline you might have to make changes in it to look for a &lt;code&gt;dist&lt;/code&gt; directory or you can change the output directory name in the build options. You can read more about all the available &lt;a href="https://vitejs.dev/config/build-options.html" rel="noopener noreferrer"&gt;build options&lt;/a&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Update Scripts
&lt;/h2&gt;

&lt;p&gt;Now, as most of our configuration part is done, we can move on to updating scripts in our &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dev Server
&lt;/h3&gt;

&lt;p&gt;First, we will have to update our start script or dev server script.&lt;br&gt;
Change your &lt;code&gt;start&lt;/code&gt; script.&lt;br&gt;
From:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts start"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can also remove the &lt;code&gt;eject&lt;/code&gt; command as it is no longer applicable.&lt;br&gt;
Remove:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"eject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts eject"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;--&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;remove&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;this&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build
&lt;/h3&gt;

&lt;p&gt;Before updating build scripts we will look into one more thing, for a production application you might be using something like &lt;a href="https://github.com/toddbluhm/env-cmd#readme" rel="noopener noreferrer"&gt;env-cmd&lt;/a&gt; for managing multiple env files for multiple environments such as development, staging, and production.&lt;br&gt;
Vite has a first-class support for something called &lt;code&gt;modes&lt;/code&gt;, we can utilize this to remove dependency on &lt;code&gt;env-cmd&lt;/code&gt; for managing multiple environments. You can read more about it in &lt;a href="https://vitejs.dev/guide/env-and-mode.html#modes" rel="noopener noreferrer"&gt;Env Variables and Modes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, let's update our build scripts.&lt;br&gt;
From:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"build:dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"env-cmd -f .env.dev react-scripts build"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"build:staging"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"env-cmd -f .env.staging react-scripts build"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"build:prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"env-cmd -f .env.prod react-scripts build"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"build:dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite build --mode dev"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"build:staging"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite build --mode staging"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"build:prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite build --mode prod"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Typescript
&lt;/h4&gt;

&lt;p&gt;For Typescript we will have to prefix build scripts with &lt;code&gt;tsc &amp;amp;&amp;amp;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unit Test
&lt;/h3&gt;

&lt;p&gt;As you may have noticed, unit tests in CRA also depend on &lt;code&gt;react-scripts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts test"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two main ways in which you keep your existing unit tests, one is using &lt;code&gt;jest&lt;/code&gt; directly as &lt;code&gt;react-scripts&lt;/code&gt; uses it under the hood and another one is using &lt;code&gt;vitest&lt;/code&gt; (this might require some migration but shouldn't be much work). &lt;/p&gt;

&lt;p&gt;I will not go into detail about migrating your unit tests, as every project has its own test setup, and generalizing it would be very difficult. You can read and learn more about both of them in &lt;a href="https://jestjs.io/docs/tutorial-react" rel="noopener noreferrer"&gt;JEST docs&lt;/a&gt; and &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Now, as all configurations and scripts have been updated, we will have to do thorough testing of all the commands, features, and pages to make sure everything is working fine and fix any issues that might arise.&lt;/p&gt;

&lt;p&gt;Once all the testing is done and we have verified that everything is working fine, we can finally remove the CRA dependency from our project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm uninstall react-scripts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, remove env-cmd or similar utility that we might not be using anymore.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm uninstall env-cmd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Extra
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Absolute Imports
&lt;/h3&gt;

&lt;p&gt;Absolute import allows us to import components, utilities, and files using their absolute path with respect to the root of the project rather than a relative path from the current file, this makes imports more readable, easy to refactor, and overall improvement in DX as you don't have to wonder from where the file is being imported.&lt;/p&gt;

&lt;p&gt;You can read more about how to implement absolute imports by googling it or you can read another great dev article &lt;a&gt;How To Create Absolute Imports In Vite React App: A step-by-step Guide&lt;/a&gt; by &lt;a href="https://dev.to/andrewezeani"&gt;Andrew Ezeani&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenSauced Interview with Evan You on Vite
&lt;/h3&gt;

&lt;p&gt;If you are interested in how, when, and why Vite was created, how it became a dominant frontend building tool, and other interesting bits from Evan You. You can watch this &lt;a href="https://youtu.be/4_uYqae42uc?si=wgMuXkbhSsiHZhGn" rel="noopener noreferrer"&gt;Why is Vite Everywhere? | Evan You&lt;/a&gt; interview by &lt;a href="https://opensauced.pizza/" rel="noopener noreferrer"&gt;OpenSauced&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Like, Follow and Discuss
&lt;/h2&gt;

&lt;p&gt;If you liked this article you can leave a reaction and if you disliked something you can leave your feedback in the comments.&lt;/p&gt;

&lt;p&gt;If you think I missed any important point or want to discuss something more in detail, we can discuss it in the comments, as it will help others who will read it in the future and maybe that person could be our future self when we need to migrate another React App from CRA to Vite.&lt;/p&gt;

&lt;p&gt;I like to connect and talk with people about tech in general and the events surrounding it. You can connect with me on &lt;a href="https://x.com/idrisGadiX" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/idris-gadi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. You can also follow me on &lt;a href="https://dev.to/idrisdev"&gt;dev.to&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>vite</category>
      <category>webdev</category>
      <category>refactorit</category>
    </item>
    <item>
      <title>Think Twice Before Using setInterval() for API Polling – It Might Not Be Ideal</title>
      <dc:creator>Idris Gadi</dc:creator>
      <pubDate>Sun, 19 May 2024 07:40:01 +0000</pubDate>
      <link>https://dev.to/igadii/think-twice-before-using-setinterval-for-api-polling-it-might-not-be-ideal-3n3</link>
      <guid>https://dev.to/igadii/think-twice-before-using-setinterval-for-api-polling-it-might-not-be-ideal-3n3</guid>
      <description>&lt;h2&gt;
  
  
  Before We Start
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Data fetching is a very simple task until it becomes complicated. Therefore I recommend that you use powerful data fetching libraries like &lt;a href="https://tanstack.com/query/latest" rel="noopener noreferrer"&gt;TanStack Query&lt;/a&gt;, &lt;a href="https://swr.vercel.app/" rel="noopener noreferrer"&gt;SWR&lt;/a&gt;, &lt;a href="https://redux-toolkit.js.org/rtk-query/overview" rel="noopener noreferrer"&gt;RTK Query&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;This post assumes that you are aware about what is API polling in RESTful architecture.&lt;/li&gt;
&lt;li&gt;All the code described is sort of a pseudo code, it's main purpose is to provide higher level understanding. The implementation might depend on the framework that you use.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With that said, let's get into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polling (The Task)
&lt;/h2&gt;

&lt;p&gt;So let's say that we have a requirement where the client(UI) requires frequent updates for a certain section but it doesn't necessarily need to be in real time, for that case we can utilise API polling.&lt;/p&gt;

&lt;h2&gt;
  
  
  setInterval() (The Intuitive Solution)
&lt;/h2&gt;

&lt;p&gt;So we need a way to call an API endpoint repeatedly after a certain amount of interval(delay). &lt;br&gt;
Which JavaScript function can we use for this? "psst...it's setInterval()"&lt;/p&gt;
&lt;h3&gt;
  
  
  API polling
&lt;/h3&gt;

&lt;p&gt;We can achieve API polling by utilising &lt;code&gt;setInterval()&lt;/code&gt; to repeatedly call fetch function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&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="cm"&gt;/*api endpoint*/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="cm"&gt;/* handle response here */&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="cm"&gt;/* handle error case here */&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;apiPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Start Polling */&lt;/span&gt;
&lt;span class="nf"&gt;apiPolling&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the client will repeatedly call the endpoint after a delay between each call where the delay is equal to the desired polling interval.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stop or Cancel polling
&lt;/h3&gt;

&lt;p&gt;When we have to stop the polling at a certain condition or cancel the polling on user's request, we have to take care of two things.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clear the setInterval function from queue.&lt;/li&gt;
&lt;li&gt;Cancel any ongoing HTTP request that hasn't responded yet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can achieve this using &lt;code&gt;clearInterval&lt;/code&gt; and &lt;code&gt;AbortController&lt;/code&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;intervalId&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;controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="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="cm"&gt;/*api endpoint*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="cm"&gt;/* handle response here */&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="cm"&gt;/* handle error case here */&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;apiPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;intervalId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Start Polling */&lt;/span&gt;
&lt;span class="nf"&gt;apiPolling&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;clearPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalId&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;controller&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* To stop or cancel polling */&lt;/span&gt;
&lt;span class="nf"&gt;clearPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we clear the polling queue by calling the &lt;code&gt;clearInterval&lt;/code&gt; function and making sure that any in-progress request is cancelled using &lt;code&gt;AbortController&lt;/code&gt;. You can read more about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/AbortController" rel="noopener noreferrer"&gt;AbortController&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues with setInterval()
&lt;/h2&gt;

&lt;p&gt;Intuitively setInterval might look like the best solution for polling until you stop and think about how it works. It &lt;strong&gt;always&lt;/strong&gt; calls the function repeatedly after a &lt;strong&gt;fixed delay&lt;/strong&gt;. This is might and will cause a host of issues, since polling in never just about calling the endpoint again again but requires careful consideration on how to handle error cases and when to poll for the next request.&lt;br&gt;
Some of the issues are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Network latency&lt;/strong&gt; or &lt;strong&gt;Unresponsive server&lt;/strong&gt; can cause the actual time to response to be greater than the polling interval, this can lead to network congestion and increased traffic on already struggling client or server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variations in response time&lt;/strong&gt; in conjunction with the above issue can cause multiple queued up requests that won't necessarily return in order, leading to a host of request handling and UX problems.&lt;/li&gt;
&lt;li&gt;Since setInterval isn't aware of the error case or stop condition, we have to &lt;strong&gt;manually stop&lt;/strong&gt; the polling for every case and with the queued up request issue it might not be simple or even possible to cancel all those requests.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqkb3soyay65vsknwkwg.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%2Fxqkb3soyay65vsknwkwg.png" alt="Illustration showing api polling issues that can arise due to setInterval" width="494" height="529"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  setTimeout() (The Proper Solution)
&lt;/h2&gt;

&lt;p&gt;Intuitively &lt;code&gt;setTimeout&lt;/code&gt; might not look like a solution for the polling at first. After all it only calls the function once after the delay and done.&lt;br&gt;
How can we use setTimeout for a task that requires a function to be called repeatedly? "Ahh...the answer is recursion".&lt;/p&gt;

&lt;p&gt;We can recursively call &lt;code&gt;setTimeout&lt;/code&gt; to achieve polling and just by the virtue of how this solution works, we can improve upon the issues encountered while using setInterval and improve user experience as well as the developer experience (talking about DX, such an original of me).&lt;/p&gt;

&lt;p&gt;Let's start with creating a recursive &lt;code&gt;setTimeout&lt;/code&gt; function that loops over itself and is invoked immediately.&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="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="cm"&gt;/* Function logic here */&lt;/span&gt;

    &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;delay&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 we can extract the function logic as a named function out of &lt;code&gt;setTimeout&lt;/code&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;function&lt;/span&gt; &lt;span class="nf"&gt;loopingLogic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* Function logic here */&lt;/span&gt;
  &lt;span class="nf"&gt;loop&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;function&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loopingLogic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&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 look at what's happening here, at first the &lt;code&gt;loop()&lt;/code&gt; is called, it invokes a &lt;code&gt;setTimeout&lt;/code&gt; which waits for the delay and calls the &lt;code&gt;loopingLogic()&lt;/code&gt;, once all the tasks in that function are performed, at the end &lt;code&gt;loop()&lt;/code&gt; function is called again, creating a recursion which calls the &lt;code&gt;loop()&lt;/code&gt; after every execution of &lt;code&gt;loopingLogic()&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Now let's say we only want to loop over the function if a certain condition is met or to stop looping when that condition is not met. We can achieve that by checking if that condition is true and only then continue to loop.&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;function&lt;/span&gt; &lt;span class="nf"&gt;loopingLogic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* Function logic here */&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* Condition is true */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;loop&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;function&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loopingLogic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&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, as we have the base logic setup, let's look at how we can achieve API polling using this pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&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="cm"&gt;/*api endpoint*/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* handle response here */&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* Condition is true */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;apiPolling&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* handle error case here */&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;apiPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* Start Polling */&lt;/span&gt;
&lt;span class="nf"&gt;apiPolling&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 walkthrough the code. We can start polling by calling the &lt;code&gt;apiPolling()&lt;/code&gt; function, it invokes a &lt;code&gt;setTimeout&lt;/code&gt; which waits for the delay before calling the &lt;code&gt;getData()&lt;/code&gt; function. &lt;/p&gt;

&lt;p&gt;In &lt;code&gt;getData()&lt;/code&gt; function we are handling the data fetching logic. We are doing few things in that function:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We are hitting the api endpoint using fetch.&lt;/li&gt;
&lt;li&gt;We wait for the response and handle the response accordingly.&lt;/li&gt;
&lt;li&gt;We check if certain condition is met before calling the &lt;code&gt;apiPolling()&lt;/code&gt; function to recursively hit the api endpoint for polling.&lt;/li&gt;
&lt;li&gt;We catch any errors and handle those errors accordingly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let's look at how this pattern of polling improves over &lt;code&gt;setInterval&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We only poll for the next request when the response from the current request is received. This solves the problem of &lt;strong&gt;network latency&lt;/strong&gt; and &lt;strong&gt;unresponsive server&lt;/strong&gt; causing a network congestion, reduced overall traffic and mitigates the issue of race conditions caused by requests that won't necessarily return in order.&lt;/li&gt;
&lt;li&gt;By checking for the base case or guard clause in the if statement, we can make sure the polling continues only if that condition is met, making it very easy to automatically stop polling and preventing other issues that might arise when something errors out and helps in better error handling.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can expand over our new polling pattern to allow users to gracefully stop or cancel polling.&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;intervalId&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;controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="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="cm"&gt;/*api endpoint*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="cm"&gt;/* handle response here */&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* Condition is true */&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;apiPolling&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* handle error case here */&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;apiPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;intervalId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&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;clearPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;intervalId&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;controller&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/* To stop or cancel polling */&lt;/span&gt;
&lt;span class="nf"&gt;clearPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;When presented with a task to create API polling, &lt;code&gt;setInterval&lt;/code&gt; might intuitively seem like the best option for this task. However as discussed above we can see that it is not the best option and can lead to some nasty issues and complicated code as we progress. Instead we can utilise the &lt;strong&gt;recursive &lt;code&gt;setTimeout&lt;/code&gt; pattern&lt;/strong&gt; to create better a solution and prevent or even improve upon the issues that might arise by using &lt;code&gt;setInterval&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Remember, whenever you have to poll an API on a remote server, always go for &lt;strong&gt;recursive &lt;code&gt;setTimeout&lt;/code&gt; pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let me know in the comments below if you found this post helpful, any points that I missed and discuss what are the different ways you like to do API polling.&lt;/p&gt;

&lt;p&gt;I like to talk about tech in general and events surrounding it. You can connect with me on &lt;a href="https://x.com/idrisGadiX" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/idris-gadi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>api</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
