<?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: Adam Nathaniel Davis</title>
    <description>The latest articles on DEV Community by Adam Nathaniel Davis (@bytebodger).</description>
    <link>https://dev.to/bytebodger</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%2F337841%2F75deba0f-8d8a-476a-b62b-557c6de1bc8f.jpg</url>
      <title>DEV Community: Adam Nathaniel Davis</title>
      <link>https://dev.to/bytebodger</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bytebodger"/>
    <language>en</language>
    <item>
      <title>Use Cases for IIFEs</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Wed, 13 Sep 2023 06:33:18 +0000</pubDate>
      <link>https://dev.to/bytebodger/use-cases-for-iifes-5gdg</link>
      <guid>https://dev.to/bytebodger/use-cases-for-iifes-5gdg</guid>
      <description>&lt;p&gt;First, I'd like to lead this article with a confession:  &lt;/p&gt;

&lt;p&gt;Whenever I'm presented with a programming concept, I immediately start searching my brain for practical ways that I would &lt;em&gt;use&lt;/em&gt; that concept.  If I can't think of a practical application for that concept, I might technically "understand" it - but I'll never truly &lt;em&gt;master&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;This can be a bit of a mental roadblock for me because someone says, "Hey, you should consider using [INSERT CONCEPT HERE]," and I nod and read a few basic articles about the concept.  But unless I can envision a logical scenario where I'll &lt;em&gt;use&lt;/em&gt; that concept, it just sits in the back of my brain, gathering dust, and doing me little good in daily programming endeavors.&lt;/p&gt;

&lt;p&gt;For many years, the Immediately Invoked Function Expression (IIFE) was exactly this type of concept.  Sure, I understood what an IIFE &lt;em&gt;was&lt;/em&gt;.  But they never really "clicked" for me because there was never any time when I thought, "Oh, wait.  I should use an IIFE here!"&lt;/p&gt;

&lt;p&gt;For whatever reason, I've actually started using IIFEs recently with some regularity.  So I figured I'd write up this article because it might help others who've never really grasped their utility.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F8k7feqc3wgxba5v9vnb1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8k7feqc3wgxba5v9vnb1.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an IIFE?
&lt;/h2&gt;

&lt;p&gt;The fully-articulated name of an IIFE basically tells you what it is.  It's a function expression that's... immediately invoked.  It differs from an &lt;em&gt;anonymous&lt;/em&gt; function in that anonymous functions can still be called numerous times, like this:&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="mi"&gt;1&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;3&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;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;item&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the example above, this is the &lt;em&gt;anonymous&lt;/em&gt; function:&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;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;It's "anonymous" because it's not stored in a variable.  So it has no "handle" that we can use to manually call the function at other points in our code.  But it's not an &lt;em&gt;immediately invoked function expression&lt;/em&gt; because it's not run... &lt;em&gt;immediately&lt;/em&gt;.  Instead, it is run once for each item that's passed into the Array prototype function &lt;code&gt;.forEach()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;IIFEs have a special syntax that tells the JavaScript engine to run the logic inside them &lt;em&gt;immediately after they're defined&lt;/em&gt;.  That syntax looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;))()&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the example above, the IIFE will console-log the value of &lt;code&gt;item&lt;/code&gt; (&lt;code&gt;1&lt;/code&gt;).  And that's fine, except...  When I look at an example like the one shown above, the IIFE just feels utterly... pointless.  I mean, if all you want to do is console-log the value of &lt;code&gt;item&lt;/code&gt;, then why wouldn't you just do this?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;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;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Of course, for this (totally simplistic) example, there really is no logical reason to use an IIFE.  And it's that basic bit of common sense that always led me to write off IIFEs as a near-pointless language construct.&lt;/p&gt;

&lt;p&gt;To be clear, I've occasionally encountered IIFEs that were written by &lt;em&gt;other&lt;/em&gt; devs.  But sooooo many times, when I see IIFEs "in the wild", I still end up scratching my head as to why the original developer even chose to use it in the first place.  My thinking went like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;IIFEs are just a block of &lt;em&gt;immediately-invoked&lt;/em&gt; code.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;So if I want that code to be &lt;em&gt;immediately-invoked&lt;/em&gt;, then why wouldn't I simply... write the code - without wrapping it inside an IIFE???&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But as I stated above, I've found several scenarios where they can truly be useful.  I hope that the following examples will help you to grasp their utility as they have for me.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbth2h1zv0bi8ipoay67t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbth2h1zv0bi8ipoay67t.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;p&gt;Let's say that you have a single file that contains a "library" of utility functions.  That may look something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// conversionUtilities.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convertUserDBToUI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convertUserUIToDB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&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;The functions above simply take objects that are formatted for the UI and converts them into objects that are formatted for the DB (and vice versa).  &lt;/p&gt;

&lt;p&gt;Of course, if these are truly meant to be "utility" functions (meaning that you'll probably need to call on them from various places throughout your application), you'll need to &lt;code&gt;export&lt;/code&gt; these functions so they can be imported at other places in the app.  That would look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// conversionUtilities.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convertUserDBToUI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convertUserUIToDB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&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;The code above would work just fine.  However, it may lead to some extraneous &lt;code&gt;import&lt;/code&gt; statements throughout your code, because anytime you need to use two-or-more of these functions in a single file, you'll need to include two-or-more &lt;code&gt;import&lt;/code&gt; statements in those files.  When you're creating "library" files that contain many related &lt;em&gt;utility&lt;/em&gt; functions, it can often be useful to have them contained within a single &lt;code&gt;export&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One way you could accomplish this is with a &lt;code&gt;class&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// conversionUtilities.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Convert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="err"&gt;{
  &lt;/span&gt;&lt;span class="nc"&gt;userDBToUI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last_name&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;userUIToDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Once again, the code above works just fine.  Here are some benefits of the above code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We no longer need to repeat &lt;code&gt;convert&lt;/code&gt; in every one of the method names, because it's implied in the name of the class.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All of our utility functions are "bundled" inside a single entity - the &lt;code&gt;Convert&lt;/code&gt; class - so they don't need to be imported individually.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But there are also a few "downsides":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Some (nay... &lt;em&gt;many&lt;/em&gt;) JS/TS developers simply abhor using the &lt;code&gt;class&lt;/code&gt; keyword.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anytime you need to use these utility functions, you first need to call something like &lt;code&gt;const convert = new Convert();&lt;/code&gt; before using the utility functions like &lt;code&gt;const userUI = convert.userDBToUI(userDB);&lt;/code&gt;.  That could become... cumbersome.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You could solve the second "problem" by exporting an &lt;em&gt;instance&lt;/em&gt; of the class, rather than exporting the class itself.  That would look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// conversionUtilities.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Convert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="err"&gt;{
  &lt;/span&gt;&lt;span class="nc"&gt;userDBToUI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last_name&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;userUIToDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convert&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;Convert&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;That saves us some keystrokes whenever we're importing the &lt;code&gt;Convert&lt;/code&gt; class.  But it still rubs some devs the wrong way because we're relying on classes.  But that's OK.  Because we can accomplish the same thing with a function:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// conversionUtilities.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Convert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userDBToUI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userUIToDB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;userDBToUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;userUIToDB&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;Here are the benefits of this approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;No more "yucky" &lt;code&gt;class&lt;/code&gt; keyword.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Again, we no longer need to repeat &lt;code&gt;convert&lt;/code&gt; in every one of the function names, because it's implied in the name of the exported function.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All of our utility functions are "bundled" inside a single entity - the &lt;code&gt;convert&lt;/code&gt; function - so they don't need to be imported individually.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But there's still at least one "downside":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Anytime you need to use these utility functions, you first need to call something like &lt;code&gt;const convert = Convert();&lt;/code&gt; before using the utility functions like &lt;code&gt;const userUI = convert.userDBToUI(userDB);&lt;/code&gt;.  That could become... cumbersome.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You could solve this "problem" by exporting the &lt;em&gt;invocation&lt;/em&gt; of the parent function, rather than exporting the parent function itself.  That would look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// conversionUtilities.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Convert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userDBToUI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userUIToDB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;userDBToUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;userUIToDB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Convert&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Honestly, this is the primary way that I usually see this done.  But there is another way - with an IIFE - that we could do this without having to first 1) define the &lt;code&gt;Convert&lt;/code&gt; function, and then 2) export the invocation of that function.  That would look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// conversionUtilities.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userDBToUI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userUIToDB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;userDBToUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;userUIToDB&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;Notice here that we didn't have to define the parent function, and then export &lt;em&gt;the invocation of that function&lt;/em&gt;.  Instead, we used an IIFE to do it all in one statement.  Now, whenever someone imports &lt;code&gt;convert&lt;/code&gt;, they'll get an object that already contains all of the utility functions inside &lt;code&gt;convert&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Is this some rock-solid no-brainer use case for IIFEs???  No.  As stated above, you can accomplish the same thing by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Exporting every single utility function individually.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Encompassing the utility functions inside a class, and then exporting an instance of that class.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Encompassing the utility functions inside a parent function, and then exporting the invocation of that function.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nevertheless, I find the IIFE approach to be just &lt;em&gt;a little bit&lt;/em&gt; cleaner.  And it's at least &lt;em&gt;one&lt;/em&gt; valid use case for IIFEs.&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fzuuefqh9y7qgdh3xvihp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fzuuefqh9y7qgdh3xvihp.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Swallowing Promises
&lt;/h2&gt;

&lt;p&gt;Async/await can be powerful tools when dealing with data calls and other asynchronous actions.  But they can also cause a bit of a cascading headache in your code - especially in strict TypeScript code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;await&lt;/code&gt; can only be used inside an &lt;code&gt;async&lt;/code&gt; function.  Imagine that you have three cascading functions that do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;FunctionA handles the result of a user action (like clicking a "Submit" button).&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the right conditions are met, FunctionA then calls some validation logic in FunctionB.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Based on the results of the validation, FunctionB may then call FunctionC, which transmits the data to the server via an asynchronous REST call.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You want to use the &lt;code&gt;await&lt;/code&gt; syntax in FunctionC, which means that you need to define it as an &lt;code&gt;async&lt;/code&gt; function.  &lt;/p&gt;

&lt;p&gt;But this means that FunctionB will now be expecting &lt;em&gt;a promise&lt;/em&gt; from FunctionC.  So... you change FunctionB to be an &lt;code&gt;async&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;But that means that FunctionA will now be expecting &lt;em&gt;a promise&lt;/em&gt; from FunctionB.  So... you change FunctionA to be an &lt;code&gt;async&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;But now the event handler that originally called FunctionA is also expecting &lt;em&gt;a promise&lt;/em&gt;.  And depending on how strict your TypeScript environment is configured, that simply may not be an option.&lt;/p&gt;

&lt;p&gt;The "cascading" effect of &lt;code&gt;async/await&lt;/code&gt; would look something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;submit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;someApiCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// handle API result&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doValidation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// check some validation&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;isValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// set some state vars&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;someCondition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;doValidation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Submit&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the example above, the TypeScript compiler will start complaining because &lt;code&gt;callApi()&lt;/code&gt; is not an &lt;code&gt;async&lt;/code&gt; function.  So you set &lt;code&gt;callApi()&lt;/code&gt; to be &lt;code&gt;async&lt;/code&gt; but... that also requires &lt;code&gt;doValidation()&lt;/code&gt; to be &lt;code&gt;async&lt;/code&gt;.  So you set &lt;code&gt;doValidation()&lt;/code&gt; to be &lt;code&gt;async&lt;/code&gt; but... that also requires &lt;code&gt;handleSubmit()&lt;/code&gt; to be &lt;code&gt;async&lt;/code&gt;.  So you set &lt;code&gt;handleSubmit()&lt;/code&gt; to be &lt;code&gt;async&lt;/code&gt; but... TypeScript might &lt;em&gt;still&lt;/em&gt; complain because the &lt;code&gt;onClick&lt;/code&gt; event handler is not configured to handle the resulting promise.&lt;/p&gt;

&lt;p&gt;At this point, you've started to shove &lt;code&gt;async&lt;/code&gt; into a lot of places where you really never wanted it to be.  And to make it even worse, TypeScript will &lt;em&gt;still&lt;/em&gt; complain about the fact that your &lt;code&gt;onClick&lt;/code&gt; handler is not handling the resulting promise.&lt;/p&gt;

&lt;p&gt;[NOTE: In plain ol' vanilla JavaScript, you can simply &lt;em&gt;ignore&lt;/em&gt; the resulting promise.  But you can't convert your entire project from TypeScript to JavaScript just because you don't wanna deal with all of these cascading usages of &lt;code&gt;async/await&lt;/code&gt;.]&lt;/p&gt;

&lt;p&gt;Luckily, an IIFE can do a load of good here.  That would look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;callApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;someApiCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// handle API result&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doValidation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// check some validation&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;isValid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;callApi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// set some state vars&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;someCondition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;doValidation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Submit&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the code above, we can now use &lt;code&gt;async/await&lt;/code&gt; inside &lt;code&gt;callApi()&lt;/code&gt; &lt;em&gt;without ever having to declare &lt;code&gt;callApi()&lt;/code&gt; as an &lt;code&gt;async&lt;/code&gt; function&lt;/em&gt;.  This works because the asynchronous call &lt;em&gt;is&lt;/em&gt; happening inside an &lt;code&gt;async&lt;/code&gt; function.  It just so happens that the &lt;code&gt;async&lt;/code&gt; function is... an IIFE &lt;em&gt;inside the &lt;code&gt;callApi()&lt;/code&gt; function&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;This is actually a use case for IIFEs that I use &lt;em&gt;a lot&lt;/em&gt;.&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F3b75mu8f0rcdtkl1w92f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F3b75mu8f0rcdtkl1w92f.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  In-place Logic
&lt;/h2&gt;

&lt;p&gt;Finally, I wanna illustrate a scenario where &lt;em&gt;in-place logic&lt;/em&gt; (i.e., the kind of logic that's provided by an IIFE) can make a lot of sense.&lt;/p&gt;

&lt;p&gt;I've recently been helping a friend with a bunch of EDI data transformations.  On the surface, the work is pretty simple.  You get a big data object that's supposed to be in a given format - maybe something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;einz&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;zwei&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;foe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;drei&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Then you have to write some transformation routine that will extract (and "massage") certain values and return a new data object in a different format, like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getGiantSpeak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;foe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fum&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;The "problem" arises when you realize that many of the vendors supplying the data will &lt;em&gt;format&lt;/em&gt; that data in many different ways.  For example, the simple logic above works just fine as long as you assume that the values in &lt;code&gt;rawData&lt;/code&gt; are simple scalar values.  &lt;/p&gt;

&lt;p&gt;But then you find that your data transformations are intermittently failing.  When you investigate the intermittent problems, you realize that &lt;em&gt;sometimes&lt;/em&gt; the vendor is submitting &lt;code&gt;rawData.fie&lt;/code&gt; as a simple string.  And &lt;em&gt;other times&lt;/em&gt; they're submitting it as an &lt;em&gt;array of strings&lt;/em&gt;.  So to fix this, you need to insert a little bit of logic at the point where &lt;code&gt;getGiantSpeak()&lt;/code&gt; is returning the &lt;code&gt;fie&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;In this scenario, I find that a simple IIFE works wonders:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;einz&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fiddler&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;zwei&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;foe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;drei&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getGiantSpeak&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fie&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&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="k"&gt;else&lt;/span&gt; 
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})(),&lt;/span&gt;
    &lt;span class="na"&gt;foe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fum&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;[NOTE: I realize that you can also accomplish the above logic with a simple ternary operator.  But the "real life" examples usually require some more "nuanced" logic that doesn't lend itself to a ternary operator.]&lt;/p&gt;

&lt;p&gt;In this scenario, the logic needed to build the new object is truly &lt;em&gt;single-use&lt;/em&gt;, and it can be much cleaner to encompass it in an IIFE.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Communication Shortcomings of Programmers</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Thu, 31 Aug 2023 20:02:24 +0000</pubDate>
      <link>https://dev.to/bytebodger/the-communication-shortcomings-of-programmers-4ej0</link>
      <guid>https://dev.to/bytebodger/the-communication-shortcomings-of-programmers-4ej0</guid>
      <description>&lt;p&gt;In my previous article (&lt;a href="https://dev.to/bytebodger/most-managers-have-no-clue-what-we-actually-do-k07"&gt;https://dev.to/bytebodger/most-managers-have-no-clue-what-we-actually-do-k07&lt;/a&gt;) I railed about my assessment that most organizations have no real concept about what programmers actually &lt;em&gt;do&lt;/em&gt;.  In that article, I spelled out many depressing truths about the many ways in which devs' efforts are often discounted.  So I'm following that article up with some advice.&lt;/p&gt;

&lt;p&gt;As frustrating as it can be to deal with people who don't really &lt;em&gt;grok&lt;/em&gt; the process of software development, I do honestly believe that we, as programmers, often bring this problem on ourselves.  You see, the simple (and painful) truth is that most programmers are pretty piss-poor communicators.  If we were great communicators, we wouldn't have chosen a career field where vast portions of our day are spent silently clacking away on a keyboard.  And while we can't make everyone else "see the light" about software development, we could do much more to ensure that we're effectively communicating with everyone outside our dev team.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ff4y7j017kfnwft765bm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ff4y7j017kfnwft765bm1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mimicking Communication
&lt;/h2&gt;

&lt;p&gt;The first thing I want to point out is something that any salesperson knows very well.  One of the most effective ways to communicate with others is to &lt;em&gt;mimic&lt;/em&gt; the style in which they already communicate.&lt;/p&gt;

&lt;p&gt;No, I'm not talking about trying to copy someone's voice or mannerisms.  I'm talking about carefully &lt;em&gt;observing&lt;/em&gt; how others choose to communicate, and then, whenever possible, communicating with them &lt;em&gt;in their chosen style&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Devs can be really crappy at this because they tend to have mastered a given communication channel - &lt;em&gt;their&lt;/em&gt; preferred communication channel - and then they blow off anyone who doesn't prefer that particular channel.&lt;/p&gt;

&lt;p&gt;For example, maybe you hate Slack.  Maybe you constantly set yourself as "Away" - even when you're right there at your desk working on code.  And to be clear, on occasion, this can make perfect sense.  But sometimes there are those who simply refuse to communicate in any way &lt;em&gt;other&lt;/em&gt; than Slack.  If you know someone like this - especially if it's someone who has input &lt;em&gt;on your work&lt;/em&gt; - then you may want to consider getting off your Slack high horse and swapping a few chat messages with them.  You won't like it.  It may not feel comfortable.  But in the end, it will keep that person from seeing you as a non-communicative jerk.&lt;/p&gt;

&lt;p&gt;In my last job I had a manager who wanted nearly everything to be written up in a Quip doc.  It didn't matter if I'd put copious notes on all my commits and pull requests.  It didn't matter if I wrote a tome of detail in the ticket.  It didn't matter if I sent him 12 Slack messages and 39 emails.  He wanted things written up in an endless stream of Quip docs.&lt;/p&gt;

&lt;p&gt;I could spend 20 paragraphs griping about this guy.  But the simple fact is that, if I really wanted to "get through" to him, it wasn't going to happen unless I started putting data &lt;em&gt;in the tool of his choice&lt;/em&gt;.  Most developers despise this.  &lt;em&gt;I&lt;/em&gt; despised this.  But getting angry about it didn't do me a damn bit of good.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ff01pdyakw212ipeptbx9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ff01pdyakw212ipeptbx9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoiding Face-Time
&lt;/h2&gt;

&lt;p&gt;When I've joined a new company and I find myself in a group video conference, I can usually identify the programmers in the meeting even before they've introduced themselves.  They're the ones who stubbornly refuse to to turn on their cameras.&lt;/p&gt;

&lt;p&gt;To be clear, I'm not claiming that you &lt;em&gt;always&lt;/em&gt; need to have your camera on.  But when you remove the video from video conferencing, you undercut a huge portion of its utility.  There are soooo many visual cues that we're subconsciously trained to pick up that fly out the window when one of the key participants just can't be bothered to turn on his camera.  &lt;/p&gt;

&lt;p&gt;Because of this, the inability to match a face to a voice fosters the mental image that some have of programmers as antisocial urchins.  If you think this has no impact on your social standing in the company, you're probably deluding yourself.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F11clgws316ywlhcj55ia.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F11clgws316ywlhcj55ia.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Technobabble
&lt;/h2&gt;

&lt;p&gt;Programmers are notorious at failing to read a room.  If you're sitting in a dev meeting - with nothing but other developers - it's fine to debate various approaches to dependency injection or to talk about the possibility that a given bug may be caused by a race condition.  But if you're sitting in one of your "normal" business meetings and talking about these concepts, you're almost certainly losing your audience.  You may even be guilty of being... a jerk.&lt;/p&gt;

&lt;p&gt;One of the reasons why "the business" can be so clueless about what we actually &lt;em&gt;do&lt;/em&gt; is because, when they ask us directly, we revel in drowning them in technobabble.  When this happens, we often feel smug in believing that we've explained &lt;em&gt;exactly&lt;/em&gt; what we're doing.  But in reality, we've only made the situation worse.&lt;/p&gt;

&lt;p&gt;Have you ever been frustrated when an inferior programmers gets promoted (or some other type of recognition) while your efforts go unnoticed?  It's probably because that doofus can describe his work (even if his work is &lt;em&gt;subpar&lt;/em&gt;) &lt;strong&gt;IN BUSINESS TERMS&lt;/strong&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F9ayvctegrh9dugnya6n1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F9ayvctegrh9dugnya6n1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Voluntary Isolation
&lt;/h2&gt;

&lt;p&gt;Lemme tell you something that some may see as "underhanded".  I've known plenty of devs in my career who simply hated talking to some (or, nearly &lt;em&gt;all&lt;/em&gt;) of the "business types".  They didn't wanna be in meetings.  They didn't wanna have to present (demo) any of their work.  They didn't wanna participate in any broader company activities.  In some of those cases, they would literally ask &lt;em&gt;me&lt;/em&gt; to handle the communication overhead.  And you know what?  &lt;em&gt;I did it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Months later, they'd be looking for a new job.  (Or even, rage-quitting.)  Why were they so frustrated?  Because &lt;em&gt;I&lt;/em&gt; had received a ton of recognition while their efforts went unnoticed.&lt;/p&gt;

&lt;p&gt;Now to be clear, I've &lt;em&gt;never&lt;/em&gt; claimed anyone else's work as my own.  And I've always gone out of my way to try to attribute credit wherever it's due.  But when those "business types" come to see &lt;em&gt;me&lt;/em&gt; as the "voice of dev", it's only inevitable that they eventually put great value in my position - and they see others as being "expendable".&lt;/p&gt;

&lt;p&gt;It's fine to "hunker down" when you're up against a tight deadline.  But if you're going out of your way to avoid any contact with anyone outside the dev team, don't go crying in your beer when those non-dev folks fail to understand your contributions.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fqjmua7z2c3wng10dr86y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fqjmua7z2c3wng10dr86y.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Combativeness/Defensiveness
&lt;/h2&gt;

&lt;p&gt;Show me a dev who doesn't enjoy a good fight and I'll show you a purple squirrel.  And yes, I'll freely admit that &lt;em&gt;I've&lt;/em&gt; too often been guilty of this myself.&lt;/p&gt;

&lt;p&gt;I find that most devs have a decent "survival instinct" when it comes to avoiding fights &lt;em&gt;outside the dev team&lt;/em&gt;.  But when it comes to matters that are code-specific?  Matters that are only debated and adjudicated &lt;em&gt;between&lt;/em&gt; software engineers...?  Well, let's just say that things can get messy.&lt;/p&gt;

&lt;p&gt;It's easy to assume that the other devs are "on your side".  It's even easy to assume that "normal" disagreements between devs are understood and tolerated as the typical process of building applications.  But I've seen far too often that the guy burying his knife deeeeeeep into my back is the same guy who didn't appreciate my argument that we should be using Zustand instead of Redux.  And when someone outside the dev team asked him to comment on me, he was all-too-quick to paint me as a malcontent.&lt;/p&gt;

&lt;p&gt;Let's be honest here:  You can't build a ton of software applications without, occasionally, having a debate with someone about the relative merits of one technical approach over another.  But if you want the broader business to focus on your &lt;em&gt;worth&lt;/em&gt; - and not on the putative headaches that you bring to the organization - then you need to be very careful about where-and-when to pick your battles.  Because once the rest of the organization hears that you're a troublemaker, they'll turn a deaf ear to any other efforts to herald your work.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>Most Managers Have No Clue What Programmers Actually Do</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Tue, 09 May 2023 04:49:22 +0000</pubDate>
      <link>https://dev.to/bytebodger/most-managers-have-no-clue-what-we-actually-do-k07</link>
      <guid>https://dev.to/bytebodger/most-managers-have-no-clue-what-we-actually-do-k07</guid>
      <description>&lt;p&gt;I've been thinking a lot lately about 1.) the avalanche of layoffs happening across the tech industry, 2.) the current push to drive remote workers back into offices, and 3.) the latest hysteria around AI.  While these issues have many different factors, I believe there's one common thread among them:  Too many "dev managers" have little-to-no-clue what software engineers actually &lt;em&gt;do&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Before I dive into the details, I'm gonna make one thing clear.  For the sake of this article, when I say "dev manager", I'm gonna use the term in a very broad sense.  Specifically, I'm using "dev manager" to refer to &lt;em&gt;any&lt;/em&gt; corporate employee who's responsible for managing the output of a software developer - or an entire team of developers.  &lt;/p&gt;

&lt;p&gt;There are many different models for managing software development.  Sometimes, your "dev manager" may be a technical coder like yourself.  But it could also be an executive (e.g., CTO), project manager, product manager, business analyst - or... nearly any other title.  But the longer I survive in this career field, the more I'm convinced that very few of them - regardless of title - ever understand the true nature of our work.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fcnvyur38k1pfxs2fn3b9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fcnvyur38k1pfxs2fn3b9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Counter-Intuitive
&lt;/h2&gt;

&lt;p&gt;On the surface, this may sound like an odd premise.  The question, "What does a software engineer &lt;em&gt;do&lt;/em&gt;?" may seem like it has a simple (and obvious) answer:  &lt;em&gt;We write software!&lt;/em&gt;  (Duhh...)  But if you've been slinging code for more than a few years, you've probably noticed that a significant portion of every day is &lt;em&gt;not&lt;/em&gt; spent in your IDE.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meetings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, there are usually many meetings that plague software engineers.  Meetings &lt;em&gt;within&lt;/em&gt; your team (e.g., standups, demos, code reviews).  Meetings with management.  Meetings with clients/stakeholders.  Even meetings that have nothing to do with your core job function.  (Like, "all-hands" meetings.)&lt;/p&gt;

&lt;p&gt;I once had a job as an "IT Manager" for a large bank.  I had a small team that handled the systems that managed the bank's public internet presence.  My role was "hands on", and I was expected to contribute directly to development projects, while still handling the duties of a frontline manager.  &lt;/p&gt;

&lt;p&gt;One day I had meetings scheduled from 9AM-10AM, 11AM-Noon, 1PM-2PM, and 3PM-4PM.  The next day, my director asked for an account of the team's progress from the previous day.  After I brought him up to speed on what had been completed (and &lt;em&gt;not&lt;/em&gt; completed), he asked me, "But what did &lt;em&gt;you&lt;/em&gt; program yesterday??"  I bluntly told him that I didn't get &lt;em&gt;any&lt;/em&gt; programming done in the previous day, because I had four meetings scheduled.  He then asked me, "But those meetings only took four hours.  Why didn't you get any coding done in the &lt;em&gt;other&lt;/em&gt; four hours?"&lt;/p&gt;

&lt;p&gt;My director had no understanding of the fact that, with four meetings throughout the day, occurring every-other-hour, I had virtually no time to sit down and actually &lt;em&gt;write code&lt;/em&gt;.  Each meeting on my schedule required at least some degree of "prep work".  And each meeting spawned a series of "take-aways" and follow-on communications that I needed to handle directly afterward.  This meant that, at most, I had &lt;em&gt;maybe&lt;/em&gt; 30 minutes to do any real coding between meetings - and for any kinda serious mental work, I just wasn't able to parachute into the middle of a task for 30 minutes and get anything meaningful accomplished.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Teamwork&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Beyond the endless series of meetings present in most software jobs, there's usually some degree of "teamwork" that goes with the job.  Maybe you need to help &lt;em&gt;someone else&lt;/em&gt; troubleshoot an issue.  Or maybe you need to help the new guy get up-to-speed.  Or maybe you need to spend some time tweaking the deployment pipeline.  Or maybe you need to review the pull requests of others.  Or maybe you need to spend some time sifting through logs.  Or... well, the list goes on and on.&lt;/p&gt;

&lt;p&gt;Most of these "teamwork" tasks rarely result in a nice clean deliverable.  They don't often satisfy a sprint task.  They don't yield a new feature to make the client happy.  They're usually best defined as &lt;em&gt;grunt work&lt;/em&gt;.  But that doesn't mean these tasks are unnecessary.  In fact, if no one does them at all, the efficient operation of your team may grind to a halt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reading/Research/Grokking&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even when you're lucky enough to have your nose stuck in code, that doesn't necessarily mean that you're &lt;em&gt;writing new code&lt;/em&gt;.  There are many estimates floating around out there about the amount of time that a dev spends &lt;em&gt;reading&lt;/em&gt; code versus &lt;em&gt;writing&lt;/em&gt; code.  And those estimates always conclude that &lt;em&gt;reading code&lt;/em&gt; is a far bigger part of the job than actually &lt;em&gt;writing code&lt;/em&gt;.  Nevertheless, when you're reading code, you're rarely delivering anything tangible that a manager would quantify as progress.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fikn7miphk8xvfpc6m65s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fikn7miphk8xvfpc6m65s.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Blind Management
&lt;/h2&gt;

&lt;p&gt;The problem with all these "soft" tasks is that management is often blind to them.  If you sit down and explain these tasks to them, they'll offer lip service as to their importance.  They'll claim that they understand that there are many tasks in a developer's job that don't lead directly to deliverables - and then... they'll turn around in the same breath and ask, "But... you're gonna have those deliverables completed today, &lt;em&gt;right&lt;/em&gt;???"&lt;/p&gt;

&lt;p&gt;To be fair, this isn't necessarily an act of wanton, willful ignorance on their part.  &lt;em&gt;Of course&lt;/em&gt; they have deliverables that they need to ensure are completed on time.  And &lt;em&gt;of course&lt;/em&gt; they're gonna be heavily focused on those deliverables and their associated timelines.  But sometimes it can be infuriating to witness the disconnect when you tell them that you had to unexpectedly burn a day standing up a new server - but they assume that the due dates will remain unaffected.&lt;/p&gt;

&lt;p&gt;You see, here's a central problem of software development:&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Those who are not directly involved in the writing of software find it extremely difficult to conceptualize the non-coding aspects of the job - or to account for them when managing expectations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;In theory, they know that there are many non-coding tasks involved in almost any software engineering milestone.  However, in practice, they struggle to grasp what those tasks are, or how long they'll take.&lt;/p&gt;

&lt;p&gt;Even when you go out of your way to brief them on all the non-coding tasks - even as the work is underway - they're still thinking in the very basic language of &lt;em&gt;deliverables&lt;/em&gt;.  Anything you must do that cannot be &lt;em&gt;directly&lt;/em&gt; tied to a deliverable runs the risk of frustrating those who are managing software development efforts.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F06cfa8av0c425anwntkv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F06cfa8av0c425anwntkv.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Beware the "Technical Manager"
&lt;/h2&gt;

&lt;p&gt;It would seem that an easy solution to this problem is to ensure that those who are &lt;em&gt;managing&lt;/em&gt; software engineers have an inherent understanding of the software engineering process itself.  In other words, we can avoid these misunderstandings as long as the "dev managers" are people who used to be coders themselves... &lt;em&gt;right&lt;/em&gt;???&lt;/p&gt;

&lt;p&gt;Ummm...&lt;/p&gt;

&lt;p&gt;While I've certainly had some bad experiences with &lt;em&gt;non&lt;/em&gt;-technical managers, I have to say that I've also had some horrific encounters with managers &lt;em&gt;who used to be coders themselves&lt;/em&gt;.  This may sound bizarre.  After all, if someone used to be writing code not-that-long-ago, then they should have an inherent understanding of all the "soft tasks" that go into a developer's typical day... &lt;em&gt;right&lt;/em&gt;???&lt;/p&gt;

&lt;p&gt;Ummm...&lt;/p&gt;

&lt;p&gt;The problem is that, in many organizations, the "dev manager" is thrown into so many meetings, and spends so much time communicating with people &lt;em&gt;outside&lt;/em&gt; the dev team, that they can scarcely keep eyes on the actual work taking place.  They can get overwhelmed trying to keep tabs on the daily efforts of a half-dozen (or more) programmers.  They rarely get time to peruse code on their own - or interface one-on-one with the developers.  This means that, far too often, the dev manager ends up looking at the same basic "metrics" (deliverables &amp;amp; timelines) that would be used by any other manager with no direct programming knowledge.&lt;/p&gt;

&lt;p&gt;Sometimes, the dev manager's technical knowledge can actually be a &lt;em&gt;liability&lt;/em&gt;.  Because they might remember what it took to do a particular task in the codebase &lt;em&gt;when they were working on the code&lt;/em&gt; (often, years in the past).  And it can be difficult for them to grok how the current state of the codebase has evolved (or... &lt;em&gt;devolved&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;[FUN SIDE NOTE: If you're ever in standup and you're tempted to say something like, "This task is taking a bit longer than expected because this particular section of code is a royal mess," you may wanna do a quick &lt;code&gt;git blame&lt;/code&gt; on the code first and see who originally wrote it.  It's entirely possible that it was written, years ago, &lt;em&gt;by your dev manager&lt;/em&gt;.  And some dev managers don't have the emotional maturity to handle comments like this very well.]&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0rmtx1e973dmrt57a3ug.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0rmtx1e973dmrt57a3ug.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Illusion of Accountability
&lt;/h2&gt;

&lt;p&gt;It took me a long time to grasp these potential disconnects between me and my dev manager.  Because modern processes of software engineering often feel as though they're inherently (even... copiously) &lt;em&gt;documented&lt;/em&gt;.  When I'm working on a task, the audit/accountability trail typically looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A task is assigned to me from some ticket management system (e.g., Jira).  The task has all sorts of meta data about the task itself.  Ideally, it has estimates and solid notes for exactly what's expected.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The coding aspects of the task are all encompassed in one-or-more commits.  I place &lt;em&gt;notes&lt;/em&gt; on each one of those commits (e.g., commit messages).&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Throughout the coding process, I give daily verbal updates (usually, during standup) explaining my progress, and expected completion times.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The completed code also contains unit tests that go a long way toward &lt;em&gt;describing&lt;/em&gt; exactly what the code is expected to do.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When I'm satisfied that the commits fulfill the requirements of the task, I submit a pull request.  I usually add &lt;em&gt;more notes&lt;/em&gt; on the pull request to aid other developers who are reviewing the code.  If other devs have questions about anything I've done, they add their own notes to the pull request, sometimes leading to discussion that's recorded directly on the PR itself.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once the code has been merged, I then add &lt;em&gt;more&lt;/em&gt; notes in the task management system, in addition to updating the status of the ticket itself.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So by the time that I'm truly done with a task, I've added my own documentation to 1.) each individual commit, 2.) the PR that encompasses the changes, and 3.) the ticket that tracks the status of the changes.  This is in addition to numerous daily verbal updates.&lt;/p&gt;

&lt;p&gt;That feels like a lot of documentation for every single task, &lt;em&gt;right&lt;/em&gt;?  And with that level of documentation, there really shouldn't be any mystery on the part of my dev manager (or anyone else on the team) as to what I'm doing or why it took as long as it did... &lt;em&gt;right&lt;/em&gt;???&lt;/p&gt;

&lt;p&gt;Ummm...&lt;/p&gt;

&lt;p&gt;Unfortunately, I've found that, far-too-often, my dev manager isn't taking the time to monitor &lt;em&gt;any&lt;/em&gt; of these communication channels.  They typically don't have the bandwidth to review commits or PRs.  They often haven't read any documentation that I've added in the task management system.  Hell... sometimes they weren't even &lt;em&gt;listening&lt;/em&gt; when I gave my verbal updates during daily standups.&lt;/p&gt;

&lt;p&gt;In other words, despite all of this status-tracking, I've run into situations, on multiple occasions, where my own dev manager wasn't aware of &lt;em&gt;any of it&lt;/em&gt;.  All they "hear" is 1.) Is the task done? and, 2.) If it's not done, when will it be done?  Beyond those basic data points, the dev manager often has little-or-no-clue about what I (or anyone else on the team) is actually &lt;em&gt;doing&lt;/em&gt; on a day-to-day basis.&lt;/p&gt;

&lt;p&gt;Last year when I was working for Amazon, I had a dev manager who used to code.  After I'd worked there for several months, he somehow got the impression that I was "falling behind".  This was despite the fact that, by numerous metrics (e.g., commits, PRs, completed tasks, LoC), I was actually doing several times more work &lt;em&gt;than anyone else on the team&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;I was documenting the ever-loving hell outta everything I was doing.  In commit messages, and PR messages, and in the ticket management system.  But none of that mattered.  Because my dev manager couldn't be bothered to actually &lt;em&gt;read&lt;/em&gt; any of it.  Even worse, I came to realize over time that, when I gave verbal updates on my work during standups, he wasn't even &lt;em&gt;listening&lt;/em&gt; to those updates.&lt;/p&gt;

&lt;p&gt;[NOTE: I'm fully aware that many metrics of programming "velocity" - like # of commits, # of PRs, etc. - are very poor measurements of productivity.  I only bring them up here because, when your metrics are several times greater &lt;em&gt;than anyone else on the team&lt;/em&gt;, it's borderline ludicrous to imply that you're somehow "falling behind".]&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fvxab53ap822kebn0wogz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fvxab53ap822kebn0wogz.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Danger For Remote Workers
&lt;/h2&gt;

&lt;p&gt;Remember, at the top of this article, how I mentioned this in relation to &lt;em&gt;remote work&lt;/em&gt;?  Well, here's where this gets really sticky for those who aren't in a traditional office space.&lt;/p&gt;

&lt;p&gt;When you're sitting in someone's office, your dev manager may have little understanding of exactly &lt;em&gt;what&lt;/em&gt; you're doing at any point in time.  But there's an incredibly basic (and... ignorant) "metric" that many in-person managers use to "gauge" your efforts:  They simple &lt;em&gt;see&lt;/em&gt; you working.&lt;/p&gt;

&lt;p&gt;As ridiculous as that sounds, the sad truth is that, for many managers, their primary "metric" for gauging your productivity is simply that they can walk by your desk and &lt;em&gt;see&lt;/em&gt; that you're... umm, working?  They may not be tied into the &lt;em&gt;actual&lt;/em&gt; work you're doing.  But at an extremely basic level, they can look up from their own desk and see that you're... typing?  Coding??  Doing &lt;em&gt;something&lt;/em&gt;???&lt;/p&gt;

&lt;p&gt;You may be staring mindlessly at the code for hours.  In fact, if they're not looking over your shoulder, they may not even know if you're even looking at the code &lt;em&gt;at all&lt;/em&gt;.  But they still get a warm-fuzzy just by knowing that you're sitting at your desk and ostensibly... working.&lt;/p&gt;

&lt;p&gt;Sadly, remote workers do not enjoy this (extremely basic) "benefit of the doubt".  If you're working remotely, and you're doing something that's not directly tied to a "hard" deliverable, it can be extremely difficult to keep your manager "in the know" about the fact that you're working hard and performing critical tasks.  This can be true even when you're going out of your way to add all those little bits of documentation (on commits, and PRs, and tickets...) that are customary in almost all software teams.&lt;/p&gt;

&lt;p&gt;So when the corporate big-wigs start fretting about last quarter's less-than-stellar results, and they begin reaching for solutions (&lt;em&gt;any&lt;/em&gt; solutions), it's easy to target the remote workers.  Because your dev manager may have little idea of what you're actually doing.  (Or, in the most extreme cases, &lt;em&gt;if&lt;/em&gt; you're actually doing anything at all.)&lt;/p&gt;

&lt;p&gt;Joe, who sits in the corporate office all day and can be seen clacking away on his keyboard, is generally "safe" during these evaluations.  It matters little that Joe may be a crappy developer.  It matters little that he spawns tsunamis of bugs and reworks.  All that &lt;em&gt;does&lt;/em&gt; matter is that your dev manager, oblivious to the &lt;em&gt;real&lt;/em&gt; work that goes into software engineering, can &lt;em&gt;see&lt;/em&gt; that Joe is constantly working.  Even though he's... not sure exactly what Joe's working on.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F6rxcbzbjd9xg5udjzhpv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F6rxcbzbjd9xg5udjzhpv.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Layoff Liability
&lt;/h2&gt;

&lt;p&gt;This same bias against remote workers plays out when it comes time to lower the axe.  Management is almost always prone to jettison the remote workers &lt;em&gt;first&lt;/em&gt;.  (Or... they do a cowardly "soft layoff" by issuing a return-to-office mandate - knowing damn well that many of the remote workers will leave of their own accord.) &lt;/p&gt;

&lt;p&gt;This happens because &lt;em&gt;soooo&lt;/em&gt; many organizations have no clue how to monitor/measure what software engineers are actually &lt;em&gt;doing&lt;/em&gt;.  Granted, if you singlehandedly rewrote your team's core application, and you did it swiftly and free of bugs, then maybe your chain-of-command understands your worth to the organization.  But if your recent tasks were more along the lines of those "soft" tasks - things like setting up servers or diving into error logs - then you may find that they're oblivious to your true value.&lt;/p&gt;

&lt;p&gt;In those scenarios, they almost always give the benefit of the doubt to the guy who's actually sitting in their office.  It doesn't matter if that guy sucks.  They can &lt;em&gt;see&lt;/em&gt; that he's working - and that's usually good enough for them.&lt;/p&gt;

&lt;p&gt;It should also be noted that there's been many stories lately about remote workers who basically had &lt;em&gt;nothing&lt;/em&gt; to do.  (I'm casting a nasty glance at you, Meta.)  And in those scenarios, that may sound like a damning statement on remote workers.  But if a company hired a bunch of remote engineers, and then couldn't be bothered to keep them busy with critical tasks, whose fault is that exactly?  &lt;/p&gt;

&lt;p&gt;And why were these Big Tech companies needlessly hoarding programming talent that they couldn't even put to work?  &lt;em&gt;Because many of the managers in those companies never properly understood what software engineers do in the first place&lt;/em&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fcncbe7nv0synbti03f9g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fcncbe7nv0synbti03f9g.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Boogeyman
&lt;/h2&gt;

&lt;p&gt;Finally, I'll mention that this inability (or unwillingness) to actually &lt;em&gt;understand&lt;/em&gt; what software engineers do represents a short-term threat to developers.  (And this is especially true of &lt;em&gt;remote&lt;/em&gt; developers.)&lt;/p&gt;

&lt;p&gt;No, I'm not claiming that AI is going to make your job obsolete.  But I &lt;em&gt;am&lt;/em&gt; claiming that, if your management doesn't fully appreciate what you do, it's far easier for them to imagine that you can be replaced (in part, or entirely) by AI tools.&lt;/p&gt;

&lt;p&gt;Let me first put this in a historical perspective.  I'm old enough to remember when outsourcing/offshoring was perceived as the biggest "threat" to software engineers.  (At least, for those developers who were not living in a prime offshoring locale.)  We now know how that played out.&lt;/p&gt;

&lt;p&gt;Offshoring is definitely still "a thing".  And it won't be going away any time soon.  But many large development projects that were offshored decades ago ended up getting pulled &lt;em&gt;back&lt;/em&gt; to their home bases.  Why??  Because the executives who thought they could game the system by offshoring everything found that the results were often... appallingly underwhelming.&lt;/p&gt;

&lt;p&gt;And why were those results so disappointing???  Because those executives &lt;em&gt;didn't properly understand what software engineers actually DO in the first place&lt;/em&gt;.  They saw development as some kind of assembly-line process that could be farmed out to the cheapest bidder.  But those projects ended up taking far longer than expected.  And even when they were delivered, the results were often suboptimal.&lt;/p&gt;

&lt;p&gt;This occurred because quality in-house software engineers perform a whole range of critical tasks that go beyond simply receiving specs and cranking out the desired algorithms.  They interview stakeholders.  They architect robust solutions.  They anticipate short-and-long-term hurdles.  They don't just type out code in their IDEs.  &lt;em&gt;They solve problems.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Of course, there's absolutely a time-and-place for offshoring.  And offshoring has settled into a valuable role for many corporations.  But there are few organizations that can successfully manage an ongoing software development operation that is entirely offshored.&lt;/p&gt;

&lt;p&gt;Unfortunately, I believe many of these same misguided strategies will play out with regard to AI.  Yes, AI is a fabulous (and rapidly evolving) tool to enhance the productivity of savvy developers.  Yes, AI's role in software engineering will almost-undoubtedly increase over time.  &lt;/p&gt;

&lt;p&gt;But before AI settles into an accepted role in corporate life, there will certainly be those who foolishly think that they can &lt;em&gt;replace&lt;/em&gt; their engineering resources with ChatGPT.  (Or any of the other evolving tools.)  And this will probably play out this way because, to this day, there are still so many people who manage development projects, but fail to understand what their developers are actually &lt;em&gt;doing&lt;/em&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fxjaw8njktbt9xmwdhmzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fxjaw8njktbt9xmwdhmzt.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  In The Next Installment...
&lt;/h2&gt;

&lt;p&gt;This article may be a &lt;em&gt;bit&lt;/em&gt;, umm... depressing.  But I don't mean it as such.  In the next article, I'll propose some strategies that you can employ, as an individual developer, to try to mitigate these hurdles.&lt;/p&gt;

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

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>Updating React State Inside Loops</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Mon, 24 Apr 2023 21:57:28 +0000</pubDate>
      <link>https://dev.to/bytebodger/updating-react-state-inside-loops-2dbf</link>
      <guid>https://dev.to/bytebodger/updating-react-state-inside-loops-2dbf</guid>
      <description>&lt;p&gt;I recently ran into a very nasty little conundrum with React.  I found a use-case where I felt it was necessary to update React state variables inside a loop.  I initially had no idea how vexing it would be.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fnf3tmxq04z9eta57kbha.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fnf3tmxq04z9eta57kbha.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  State Management Under-The-Hood
&lt;/h2&gt;

&lt;p&gt;Before I dive into this problem, there are a few basic facts that you need to understand about how React manages state variables.  This should be second nature to all of you salty old React vets out there.  But it's important to establish these ground rules before we dive in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React state is asynchronous&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you update a React variable, the subsequent mutation occurs asynchronously.  You can prove it out with an example like this:&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCounter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCounter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;Increment&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;From a UX perspective, the example above works just fine.  Every time you click &lt;code&gt;Increment&lt;/code&gt;, the counter value updates.  However, the &lt;code&gt;console.log()&lt;/code&gt; output will always be one update &lt;em&gt;behind&lt;/em&gt;.  This happens because the update occurs asynchronously.  And when the code hits the &lt;code&gt;console.log()&lt;/code&gt;, the value has not yet been updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React &lt;em&gt;batches&lt;/em&gt; state updates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;React does a lot of work behind the scenes to optimize performance.  Normally, this optimization doesn't really phase us.  Because the typical flow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A user performs some action (like clicking a button).&lt;/li&gt;
&lt;li&gt;The state variable is updated.&lt;/li&gt;
&lt;li&gt;React's &lt;em&gt;reconciliation&lt;/em&gt; process is triggered.&lt;/li&gt;
&lt;li&gt;This process realizes that there's now a diff between the virtual DOM and the actual DOM.&lt;/li&gt;
&lt;li&gt;React updates the actual DOM to reflect the changes in the virtual DOM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the vast majority of circumstances this all happens so fast as to appear, to the naked eye, as instantaneous.  But the good folks who built React also put in some safeguards to protect against those instances where a developer tries to fire off a rapid series of state updates.&lt;/p&gt;

&lt;p&gt;Of course, this optimization is, by and large, a very &lt;em&gt;good&lt;/em&gt; thing.  But it can be baffling when you feel that those successive updates are truly necessary.  Specifically, React goes out of its way to ensure that all state updates that are triggered &lt;em&gt;within a loop&lt;/em&gt; will not actually be rendered until the loop has finished running.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F58cu04za6ezxwgfqn5vz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F58cu04za6ezxwgfqn5vz.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Case Study For State Updates Inside A Loop
&lt;/h2&gt;

&lt;p&gt;My website - &lt;a href="https://paintmap.studio" rel="noopener noreferrer"&gt;https://paintmap.studio&lt;/a&gt; - does image/color manipulation.  Although the functionality works precisely as designed, this does present a few challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Images have the potential to be large.  I &lt;em&gt;could&lt;/em&gt; introduce some artificial limits on the size of the image file (either in raw kilobytes or in height/width dimensions), but doing so would undermine much of the utility of the application.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The images are not being uploaded and processed &lt;em&gt;on a server&lt;/em&gt;.  It's a single page application with no backend component.  It runs entirely in the browser.  So I can't, for example, upload an image, commence some intensive processing, and then promise to email the user a link to the finished product when the process is complete.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The amount of time it takes to process an image is largely dependent upon the processing &lt;em&gt;options&lt;/em&gt; that are chosen by the user.  For example, processing an image with the RGB color space is much faster than using Delta-E 2000.  Dithering an image takes more time than if dithering is avoided.  So in theory, I could introduce some artificial limits on the number of options available to the user.  But again, this would undermine much of the utility of the application itself.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The simple fact is that sometimes I want to transform an image, of a certain size, and with a certain number of processor-intensive options, that's gonna take a little &lt;em&gt;time&lt;/em&gt; to complete.  When that happens, I don't want the user wondering if the application has crashed.  I want them to understand that everything is chugging along as-planned and their newly-processed image will be completed soon.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fz7bq2hf17bhq2mabnlu9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fz7bq2hf17bhq2mabnlu9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Progress Bar
&lt;/h2&gt;

&lt;p&gt;One of the most time-tested ways to let the user know that processing is continuing as-planned is to give them some kind of progress bar.  Ideally, that progress bar updates in real-time as the code works through its machinations.  &lt;/p&gt;

&lt;p&gt;Of course, this is nothing new at all.  Applications have been providing this type of user feedback for decades.  But when I tried to implement this in React with Material UI's &lt;code&gt;&amp;lt;CircularProgress&amp;gt;&lt;/code&gt; component, I ran into some really nasty headaches.&lt;/p&gt;

&lt;p&gt;Because I don't want to confuse the matter by trying to drop you right into the middle of Paintmap Studio's code, I've instead created a simplified demo in CodeSandbox to illustrate the problem.  You can view that demo here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/update-react-state-in-a-loop-04b9ek" rel="noopener noreferrer"&gt;https://codesandbox.io/s/update-react-state-in-a-loop-04b9ek&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fadacu95hzpfeanzmy7bx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fadacu95hzpfeanzmy7bx.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem - Illustrated
&lt;/h2&gt;

&lt;p&gt;In the Code Sandbox demo, I've created an artificially-slow process to illustrate the issue.  When you load this demo, it gives you a single button on the screen titled &lt;code&gt;START SLOW PROCESS&lt;/code&gt;.  The idea is that, once you click that button, a somewhat lengthy process will be triggered.  &lt;/p&gt;

&lt;p&gt;But we don't want the user wondering whether the site's crashed. So once the button is clicked, we need to have an interstitial overlay shown on screen.  The overlay let's the user know that the process is underway, and ideally, gives them a dynamic progress indicator that lets them know how far the process is from being completed.&lt;/p&gt;

&lt;p&gt;We'll start the illustration with &lt;code&gt;App.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// App.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AppState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;showProcessing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowProcessing&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt;
        &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
          &lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;setShowProcessing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;showProcessing&lt;/span&gt;
        &lt;span class="p"&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="nx"&gt;UI&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;/AppState.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;App.js&lt;/code&gt; is mostly just a wrapper for the UX.  However, I'm using the Context API to establish some state variables that will be useful in the downstream code.  &lt;code&gt;progress&lt;/code&gt; represents the completion percentage of our &lt;code&gt;SLOW PROCESS&lt;/code&gt;.  &lt;code&gt;showProcessing&lt;/code&gt; determines whether the progress interstitial should be shown.&lt;/p&gt;

&lt;p&gt;Now let's take a look at &lt;code&gt;UI.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// UI.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showProcessing&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;runSlowProcess&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSlowProcess&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;handleSlowProcessButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;runSlowProcess&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Backdrop&lt;/span&gt;
        &lt;span class="nx"&gt;sx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
          &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;drawer&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}}&lt;/span&gt;
        &lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;showProcessing&lt;/span&gt;&lt;span class="p"&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="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&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;textAlignCenter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Box&lt;/span&gt;
            &lt;span class="nx"&gt;sx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
              &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inline-flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;relative&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CircularProgress&lt;/span&gt;
              &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&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;success&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&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;determinate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Box&lt;/span&gt;
              &lt;span class="nx"&gt;sx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
                &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;absolute&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
              &lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Typography&lt;/span&gt; 
                &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&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;white&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
                &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="o"&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;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
                &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&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;caption&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Typography&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Box&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Box&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;Slow&lt;/span&gt; &lt;span class="nx"&gt;Process&lt;/span&gt; &lt;span class="nx"&gt;Running&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Backdrop&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt;
        &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSlowProcessButton&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&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;small&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&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;contained&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;Start&lt;/span&gt; &lt;span class="nx"&gt;Slow&lt;/span&gt; &lt;span class="nx"&gt;Process&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;First, the named components in the JSX, like &lt;code&gt;&amp;lt;Backdrop&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Box&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;CircularProgress&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Typography&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;Button&amp;gt;&lt;/code&gt; come from Material UI.&lt;/p&gt;

&lt;p&gt;Second, the component leverages the &lt;code&gt;AppState&lt;/code&gt; context that was established in &lt;code&gt;App.js&lt;/code&gt;.  Specifically, we'll be using &lt;code&gt;showProcessing&lt;/code&gt; to toggle the visibility of the interstitial layer.  And we'll be using &lt;code&gt;progress&lt;/code&gt; to show the user how far the &lt;code&gt;SLOW PROCESS&lt;/code&gt; is from completion.&lt;/p&gt;

&lt;p&gt;Finally, this component also imports a custom Hook.  That Hook is called &lt;code&gt;useSlowProcess()&lt;/code&gt;.  Let's take a look at that:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// useSlowProcess.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useSlowProcess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowProcessing&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppState&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;runSlowProcess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setShowProcessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;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;1&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;101&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="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;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&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="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;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&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="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;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;l&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="c1"&gt;// do the stuffs&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;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="nf"&gt;setProgress&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="nf"&gt;setShowProcessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;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;Elapsed time:&lt;/span&gt;&lt;span class="dl"&gt;"&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;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;seconds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;runSlowProcess&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;useSlowProcess()&lt;/code&gt; returns a single function: &lt;code&gt;runSlowProcess()&lt;/code&gt;.  &lt;code&gt;runSlowProcess()&lt;/code&gt; does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It establishes a &lt;code&gt;startTime&lt;/code&gt; so we can calculate just how long the &lt;code&gt;SLOW PROCESS&lt;/code&gt; actually takes.  (After playing with this repeatedly on Code Sandbox, I can tell you that it takes ~27 seconds to complete.)&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It ensures that our &lt;code&gt;progress&lt;/code&gt; variable starts at &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It then sets &lt;code&gt;showProcessing&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; so the user will see the in-progress interstitial.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It then launches into the &lt;code&gt;SLOW PROCESS&lt;/code&gt;.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The outer loop runs for 100 iterations.  This means that every completion of the outer loop essentially means that we've completed 1% of the overall process.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After each percentage is completed, we &lt;code&gt;console.log()&lt;/code&gt; the current progress &lt;em&gt;and&lt;/em&gt; we update the &lt;code&gt;progress&lt;/code&gt; variable.  Remember, that variable will be used to show the user how close we are to completion.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the process is complete, we set &lt;code&gt;showProcessing&lt;/code&gt; back to &lt;code&gt;false&lt;/code&gt;.  This should remove the in-progress interstitial.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, we &lt;code&gt;console.log()&lt;/code&gt; the total number of seconds that it took to complete the &lt;code&gt;SLOW PROCESS&lt;/code&gt;.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So what happens when we run this code???  Well... it's very disappointing.&lt;/p&gt;

&lt;p&gt;When the user clicks the &lt;code&gt;START SLOW PROCESS&lt;/code&gt; button, there is &lt;em&gt;no&lt;/em&gt; interstitial shown on screen.  This also means that the user sees no &lt;code&gt;&amp;lt;CircularProgress&amp;gt;&lt;/code&gt; bar, with &lt;em&gt;no&lt;/em&gt; constantly-updated completion percentage.&lt;/p&gt;

&lt;p&gt;But why does this happen?&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F9pvzrbmmwhtt7cqvn9aa.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F9pvzrbmmwhtt7cqvn9aa.jpeg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Batching Headaches
&lt;/h2&gt;

&lt;p&gt;This is where we run head-first into the problems with React's batch updating of state variables.  React sees that we're setting &lt;code&gt;showProcessing&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; near the beginning of &lt;code&gt;runSlowProcess()&lt;/code&gt; but we're &lt;em&gt;also&lt;/em&gt; setting it to &lt;code&gt;false&lt;/code&gt; near the end of the process.  So the batched result is that it simply sets &lt;code&gt;showProcessing&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;.  Of course, it was &lt;em&gt;already&lt;/em&gt; &lt;code&gt;false&lt;/code&gt; when we began the process.  So setting the previous value of &lt;code&gt;false&lt;/code&gt; to... &lt;code&gt;false&lt;/code&gt; results in the user never even seeing the in-progress interstitial.&lt;/p&gt;

&lt;p&gt;Even if we solved that problem, the user would never see any of the percent updates to the &lt;code&gt;progress&lt;/code&gt; variable displayed inside the &lt;code&gt;&amp;lt;CircularProgress&amp;gt;&lt;/code&gt; component.  &lt;em&gt;Why?&lt;/em&gt;  Because React sees that the state variable &lt;code&gt;progress&lt;/code&gt; is being updated repeatedly through the outer &lt;code&gt;for&lt;/code&gt; loop.  Thus, it &lt;em&gt;batches&lt;/em&gt; all of those updates into a single value.  Of course, this completely undermines the whole purpose of having a progress indicator in the first place.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ffxhk58twtufjk565moxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffxhk58twtufjk565moxg.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frustrating (Non)Help
&lt;/h2&gt;

&lt;p&gt;Remember, the &lt;code&gt;&amp;lt;CircularProgress&amp;gt;&lt;/code&gt; component comes from Material UI.  And Material UI has a ton of helpful documentation that's supposed to show you how to use their components.  So my first step was to go back to that documentation for help.  But... it was of no help whatsoever.&lt;/p&gt;

&lt;p&gt;Here's the code sample that Material UI gives you to illustrate how you can update the &lt;code&gt;progress&lt;/code&gt; value in the &lt;code&gt;&amp;lt;CircularProgress&amp;gt;&lt;/code&gt; component:&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;CircularDeterminate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prevProgress&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;prevProgress&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prevProgress&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CircularProgress&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;determinate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;To be clear, Material UI's code sample "works".  I mean... it &lt;em&gt;does&lt;/em&gt; dynamically update the &lt;code&gt;progress&lt;/code&gt; value inside the &lt;code&gt;&amp;lt;CircularProgress&amp;gt;&lt;/code&gt; component.  But this is one of the few times that I found their documentation to be borderline useless.&lt;/p&gt;

&lt;p&gt;You see, they're using &lt;code&gt;useEffect()&lt;/code&gt;, in conjunction with &lt;code&gt;setInterval()&lt;/code&gt;, to &lt;em&gt;blindly&lt;/em&gt; update the &lt;code&gt;progress&lt;/code&gt; value based on nothing more than a predetermined delay of 800 milliseconds.  While that works fine for displaying a rote example of how the component renders, it does nothing to tell us how we can tie the &lt;code&gt;progress&lt;/code&gt; value to an actual, &lt;em&gt;meaningful&lt;/em&gt; calculation based upon the true &lt;em&gt;progress&lt;/em&gt; of the process.&lt;/p&gt;

&lt;p&gt;Faced with this very useless example, I then did what any lifelong developer would do:  I started googling.  But almost all of the posts I found on places like Stack Overflow were similarly useless.&lt;/p&gt;

&lt;p&gt;The issue you encounter when you google this problem is that nearly every developer has the exact same "answer":&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Don't update React state variables in a loop.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;While I understand that there are &lt;em&gt;many&lt;/em&gt; scenarios where you do want to avoid repeatedly updating React state inside a loop, the simple fact is that &lt;em&gt;this&lt;/em&gt; use case is the quintessential use case where you absolutely &lt;em&gt;should&lt;/em&gt; be updating React state inside a loop.  Because the &lt;code&gt;progress&lt;/code&gt; value should, ideally, be calculated based upon the actual progress of the algorithm - &lt;strong&gt;NOT&lt;/strong&gt; based upon some mindless &lt;code&gt;setInterval()&lt;/code&gt; delay.&lt;/p&gt;

&lt;p&gt;I actually encounter this sort of &lt;em&gt;non&lt;/em&gt;-help all the time.  You're trying to solve some kind of sticky programming problem.  But rather than providing any &lt;em&gt;meaningful&lt;/em&gt; help, the mouth-breathers simply reply that you shouldn't be doing this at all.&lt;/p&gt;

&lt;p&gt;It's like seeing someone's post about how they can't figure out how to cook a proper souffle without it collapsing and becoming a mess - and some smartass troll in the cooking forum responds by saying:&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;You shouldn't be cooking souffles anyway.  Just make an omelette.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;Wow. That's &lt;em&gt;sooooo&lt;/em&gt; helpful.  Thankfully, I did eventually solve the problem...&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fqwxbakj9qkti7tbb0cy3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fqwxbakj9qkti7tbb0cy3.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Promises To The Rescue
&lt;/h2&gt;

&lt;p&gt;The key to solving this one is that you have to introduce &lt;em&gt;a delay&lt;/em&gt;.  If you look at what's happening in Material UI's example, they're invoking a delay with &lt;code&gt;setInterval()&lt;/code&gt;.  But the &lt;em&gt;real&lt;/em&gt; reason why their example "works" is because the &lt;code&gt;setInterval()&lt;/code&gt; is embedded within &lt;code&gt;useEffect()&lt;/code&gt;.  This creates a kind of feedback loop where the state variable is updated inside &lt;code&gt;useEffect()&lt;/code&gt;, then the reconciliation process updates the DOM, which triggers another call to &lt;code&gt;useEffect()&lt;/code&gt;, which then updates the variable again, and so on and so on...&lt;/p&gt;

&lt;p&gt;Of course, in my example, I'm trying to track the progress of a function inside a Hook.  So it's not terribly useful to rely upon &lt;code&gt;useEffect()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But there's another way to invoke a delay without using &lt;code&gt;useTimeout()&lt;/code&gt; or &lt;code&gt;useInterval()&lt;/code&gt;.  You can use a &lt;em&gt;promise&lt;/em&gt;.  Promises (and their associated &lt;code&gt;async/await&lt;/code&gt; convention) basically knock React out of its batch update mentality.&lt;/p&gt;

&lt;p&gt;The updated &lt;code&gt;useSlowProcess()&lt;/code&gt; code looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// useSlowProcess.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useSlowProcess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowProcessing&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppState&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;runSlowProcess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setShowProcessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="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;1&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;101&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="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;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&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="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;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;k&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="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;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;l&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="c1"&gt;// do the stuffs&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;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="nf"&gt;setProgress&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;setShowProcessing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;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;Elapsed time:&lt;/span&gt;&lt;span class="dl"&gt;"&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;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;seconds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;runSlowProcess&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 when you click the &lt;code&gt;START SLOW PROCESS&lt;/code&gt; button, the progress interstitial shows up on the screen, including the &lt;code&gt;&amp;lt;CircularProgress&amp;gt;&lt;/code&gt; component with it's constantly updated &lt;code&gt;progress&lt;/code&gt; indicator.&lt;/p&gt;

&lt;p&gt;Notice a few things about this approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I invoke the delay directly &lt;em&gt;after&lt;/em&gt; I've updated the &lt;code&gt;progress&lt;/code&gt; value inside the &lt;code&gt;for&lt;/code&gt; loop. This has the side effect of knocking React out of the batch update process.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;length&lt;/em&gt; of the delay is immaterial.  As you can see, I'm invoking a delay of &lt;strong&gt;&lt;em&gt;ZERO&lt;/em&gt;&lt;/strong&gt; milliseconds.  That may seem illogical, but it's all that's needed to trigger DOM updates in React.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I just wanna be clear that, in the vast majority of instances, it's truly a solid idea to &lt;em&gt;avoid&lt;/em&gt; doing repeated React state updates inside a loop.  But I wanted to highlight this use case because, when you're trying to give the user real-time info on the status of an ongoing process, it's one potential scenario where it makes total sense to do it.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Test-Driven Daydreams</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Wed, 19 Apr 2023 20:42:50 +0000</pubDate>
      <link>https://dev.to/bytebodger/test-driven-daydreams-297g</link>
      <guid>https://dev.to/bytebodger/test-driven-daydreams-297g</guid>
      <description>&lt;p&gt;My thoughts on Test-Driven Development (TDD) have certainly... &lt;em&gt;fluctuated&lt;/em&gt; over time.  At this point, it's far from being a new concept.  Wikipedia traces its origins to the early 2000s.  I believe that I first heard of it about a dozen years ago.  During that time, my personal exposure to it has varied wildly from one company to the next.&lt;/p&gt;

&lt;p&gt;This is not my pro-TDD fanboy article.  Nor is it my click-baity anti-TDD rant.  Rather, I'm writing about it now because I think I've settled on an approach to TDD that works &lt;em&gt;for me&lt;/em&gt;.  Of course, your mileage may vary...&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mj3j00kt0f4cta29335.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3mj3j00kt0f4cta29335.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TDD Fanboys
&lt;/h2&gt;

&lt;p&gt;My first "problem" with TDD, similar to problems that I experience with almost &lt;em&gt;any&lt;/em&gt; other approach to dev, is that it spawns its own legion of fanboys.  Granted, this is true of sooooo many other aspects of software development.  But if you're trying to have a calm, rational discussion with someone about TDD, it's nearly impossible to do so with those who've already drank the TDD Kool-Aid.&lt;/p&gt;

&lt;p&gt;So while I know that these points will do absolutely nothing to quiet the TDD mouth-breathers, I'm still gonna point out a few basic &lt;strong&gt;facts&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TDD is not a "cure-all".&lt;/strong&gt;&lt;br&gt;You can be a great developer without ever worrying about TDD.  You can be a crappy developer who adheres tightly to TDD.  TDD &lt;em&gt;can&lt;/em&gt; be a great tool.  Just like a hammer can be a great tool.  But that doesn't mean that it's the "right" tool for every job.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TDD is too often confused with general concepts of &lt;em&gt;unit testing&lt;/em&gt;.&lt;/strong&gt;&lt;br&gt;Writing unit tests does not (necessarily) mean that you're following TDD.  Having X% of test coverage does not qualify (or disqualify) you as doing TDD.  And doing TDD doesn't solve the ongoing questions of exactly what should-or-should-not be tested within a given codebase.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The above &lt;strong&gt;facts&lt;/strong&gt; are not meant as any kinda "take-down" of TDD.  But I've grown a little tired of hearing the TDD fanboys talk about it as though it solves many issues around testing - that it doesn't really solve at all.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F141tawgezs0v9xa2xs51.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F141tawgezs0v9xa2xs51.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenges of TDD Groupthink
&lt;/h2&gt;

&lt;p&gt;Most of my qualms haven't been with the &lt;em&gt;concepts&lt;/em&gt; of TDD.  They've been with the difficulty in getting everyone on a team to adhere to those concepts - or to even &lt;em&gt;agree&lt;/em&gt; on what those concepts are.  I've been in some shops where TDD was talked about like an unreachable dream.  I've been in others where it was presented as some kind of standard, that we &lt;em&gt;all&lt;/em&gt; should be following, and then... &lt;em&gt;no one&lt;/em&gt; followed it.  I've been in places where it was openly agreed that we would be implementing TDD - and then those guidelines were blatantly ignored as soon as we faced the first pending deadline.&lt;/p&gt;

&lt;p&gt;I've also seen scenarios where an underlying desire for TDD "purity" culminated in abandonment of the approach altogether.  For example, some believe that the "right" way to do TDD is to have &lt;em&gt;someone else&lt;/em&gt; write the original tests, before you begin writing the code that would adhere to those tests.  And that approach isn't "wrong".  But it requires a lot of coordination and team cohesion.  And when that coordination fails to materialize... everyone just drops the whole TDD idea and goes back to doing things as they did before.&lt;/p&gt;

&lt;p&gt;Let me absolutely clear on this:  I've been in several different shops where TDD was discussed/proposed/championed, but I've &lt;em&gt;never&lt;/em&gt; been in a dev shop where it was actually implemented as a regular practice.  And I'll also be honest here and admit that, when the rest of the team easily abandoned their TDD dreams, I tended to fall inline with the group.&lt;/p&gt;

&lt;p&gt;I also wanna be crystal clear in saying that I'm sure there are dev shops out there that rigidly adhere to TDD.  I'm not claiming that they don't exist.  I'm just stating that, in my anecdotal experience, TDD is frequently &lt;em&gt;talked about&lt;/em&gt;, but has rarely/never been truly &lt;em&gt;implemented&lt;/em&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny5wnrc8fr752weovqba.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny5wnrc8fr752weovqba.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Going It Alone
&lt;/h2&gt;

&lt;p&gt;One of my recent "aha" moments was around the idea that I don't need to have Full Team Buy-In in order to do TDD.  In other words, if Joe and Mary on my team don't bother with TDD, that doesn't mean that I can't still write &lt;em&gt;my&lt;/em&gt; code with TDD.  In the past, I tended to see this as a team-centric decision.  And to be frank, it &lt;em&gt;is&lt;/em&gt; better if the whole team is aligned on something like this.  But that doesn't mean that everyone has to be in lockstep.&lt;/p&gt;

&lt;p&gt;That may sound like I'm advocating for you to "cowboy" your way through the dev process.  But I think it's perfectly reasonable to say, "This is the way that &lt;em&gt;I&lt;/em&gt; know to write high-quality code.  So this is the way that &lt;em&gt;I'm&lt;/em&gt; going to attack this problem."  In practice, there are many aspects of dev where I enforce my own personal coding standards.  For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If I'm building a new database-driven app/feature, I start &lt;em&gt;first&lt;/em&gt; with the database.  I design the database schema (or, at least, I ensure that I fully understand the existing schema) before I ever begin writing the first line of code.  I don't ask others if they want me to do it this way.  I don't worry whether the others will design their features with the same approach.  &lt;em&gt;For me&lt;/em&gt;, I know the best way to get the feature built.  So I just go about doing it that way.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Similarly, if I'm integrating with web services (or, if I'm &lt;em&gt;building&lt;/em&gt; those web services), I &lt;em&gt;always&lt;/em&gt; ensure that I have an up-to-date Swagger file (or other endpoint schema model) before I begin writing the code that will consume those services.  If others don't build &lt;em&gt;their&lt;/em&gt; code in the same way, that's fine.  But I'm not going to abandon the best way that I know to deliver quality code simply because others eschew those methods.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So my point here is that, while it would be great if your whole team was on the same TDD page, you don't need to confine TDD to being a team-level decision.  If you find that you are writing better quality code by using TDD methods, then do it.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptsluntevbfa1y3nvd9g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptsluntevbfa1y3nvd9g.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Contract&lt;/em&gt;-Driven Development
&lt;/h2&gt;

&lt;p&gt;Another recent "aha" moment, for me, has been that, IMHO, TDD isn't really &lt;em&gt;test&lt;/em&gt;-driven development, it's &lt;em&gt;contract&lt;/em&gt;-driven development.  What do I mean by that??&lt;/p&gt;

&lt;p&gt;Well, in the examples above, I explained how I don't start building a database-driven application until I've either &lt;em&gt;designed&lt;/em&gt; the database schema, or I at least &lt;em&gt;understand&lt;/em&gt; the existing schema.  Because the data layer, in many respects, defines what your application can-or-cannot do.  So if you're trying to build features without understanding the underlying data model, you're probably setting yourself up for some nasty rewrites down the line.  If I'm integrating with endpoints, the same concept applies.&lt;/p&gt;

&lt;p&gt;But what about when you're writing code that doesn't directly hit a database or an endpoint?  Is there any particular data contract that you need to be aware of?  Yes.&lt;/p&gt;

&lt;p&gt;Almost all code contains a proliferation of smaller code bits.  Those "bits" are typically called &lt;em&gt;methods&lt;/em&gt;, or &lt;em&gt;functions&lt;/em&gt;, or &lt;em&gt;components&lt;/em&gt;.  Methods / functions / components all share some common features.  Specifically, each one expects zero-to-many &lt;em&gt;inputs&lt;/em&gt;, and they all return zero-to-many &lt;em&gt;outputs&lt;/em&gt;.  Those inputs and outputs are... your &lt;em&gt;data contract&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When you first started coding, you probably began by cranking out functions (or methods, or components) where the inputs-and-outputs where defined "on the fly".  You added new inputs (arguments) as needed.  And you added new outputs (&lt;code&gt;return&lt;/code&gt; values) as needed.  And when you were done, hopefully the function &lt;em&gt;did&lt;/em&gt; what you &lt;em&gt;wanted&lt;/em&gt; it to do.&lt;/p&gt;

&lt;p&gt;TDD flips that equation around.  It forces you to define (and thus, think deeply) about exactly what those inputs/outputs should be before you ever begin writing the function.  In other words, TDD forces you to define the &lt;em&gt;data contract&lt;/em&gt; for a function before you ever write the function.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs9xunetbje3nb4qseqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs9xunetbje3nb4qseqt.png" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuous Feedback
&lt;/h2&gt;

&lt;p&gt;TDD has another benefit that I believe is rarely discussed.  This benefit is that of &lt;em&gt;continuous feedback&lt;/em&gt;.  If you've worked in any professional dev environment, you're probably accustomed to feedback.  You receive it every time you submit a pull request, or any time your team does broader code reviews.  If you're accustomed to pair programming, you may also receive live feedback in real-time.&lt;/p&gt;

&lt;p&gt;But coding is often a solitary experience.  Unless you're doing a live coding session, your first real feedback on any piece of code often comes at the point when you feel your code is &lt;em&gt;completed&lt;/em&gt; and you're submitting it to be reviewed/merged.  But if you're following TDD, you start to receive that feedback from the moment that you begin coding.&lt;/p&gt;

&lt;p&gt;By defining the tests &lt;em&gt;first&lt;/em&gt; (tests which should, initially, &lt;em&gt;fail&lt;/em&gt; - until you complete the code), you're defining, upfront, a data contract.  And then, as you write that code, the tests continually tell you whether or not it passes.  This is doubly useful once you move on to &lt;em&gt;refactoring&lt;/em&gt; your code.&lt;/p&gt;

&lt;p&gt;While there's nothing inherently "wrong" about coding outside of TDD, there are some worrisome behaviors that often exist when people are coding without it.  For example, most non-TDD devs don't even bother to run the tests &lt;em&gt;until they've "completed" their code&lt;/em&gt;.  Only once they notice that something's failing (and thus, they can't &lt;em&gt;commit&lt;/em&gt; it) will they start to pay close attention to the tests.  But TDD devs are much more likely to have the tests running &lt;em&gt;during the entire time that they're coding&lt;/em&gt;.  They do this because they're constantly getting "feedback" on the code that they're writing - and they can correct errors much earlier in the process.&lt;/p&gt;

&lt;p&gt;Non-TDD devs are also much more likely to craft tests that encompass cognitive biases.  (Specifically, &lt;em&gt;confirmation&lt;/em&gt; bias.)  They write code.  &lt;em&gt;Then&lt;/em&gt; they slap some tests on it.  And do the tests pass?  &lt;em&gt;Of course they do!&lt;/em&gt;  Because, whether they realize it or not, they've written tests that are designed to pass what they've written - rather than writing tests that are designed to confirm the desired functionality.&lt;/p&gt;

&lt;p&gt;In this model, the tests are not providing &lt;em&gt;continuous&lt;/em&gt; feedback.  They're only providing "feedback" after-the-fact.  Even worse, this "feedback" too-often only serves to confirm what the dev has already coded.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwminds2adew9run2cgom.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwminds2adew9run2cgom.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Time Crunches
&lt;/h2&gt;

&lt;p&gt;The biggest problem that standalone TDD advocates run into is: the time crunch.  There's been a lot of research that indicates that, in the long run, proper adherence to TDD should &lt;em&gt;save&lt;/em&gt; you and your team time.  But &lt;em&gt;in the short run&lt;/em&gt;, TDD practices can feel like a burden.&lt;/p&gt;

&lt;p&gt;Any time you need to spend significant effort &lt;em&gt;pre-planning&lt;/em&gt; your work, that's an additional time burden.  If you're writing your tests &lt;em&gt;first&lt;/em&gt;, and you're putting in significant effort to ensure that those tests are meaningful and helpful, then that absolutely qualifies as "pre-planning".  So it is possible that, on at least &lt;em&gt;some&lt;/em&gt; of your tasks, a TDD approach will make you look slower in the eyes of your fellow devs.  This is &lt;em&gt;especially&lt;/em&gt; true if those devs don't follow TDD practices.&lt;/p&gt;

&lt;p&gt;Consider the following potential scenario:&lt;/p&gt;

&lt;p&gt;Your team hasn't adopted TDD as a standard.  Of course, you can still write &lt;em&gt;your&lt;/em&gt; code with TDD.  But sometimes the difference in approaches will be apparent as you work through a sprint.&lt;/p&gt;

&lt;p&gt;Imagine that Joe is on your team.  He can't be bothered with TDD. You've both been given tasks of similar scope, each estimated to take a day of effort.&lt;/p&gt;

&lt;p&gt;Joe finishes his task by noon.  Joe's actually a really &lt;em&gt;good&lt;/em&gt; developer, and his code looks fine.  (Remember:  Being a non-TDD developer doesn't mean that you're a &lt;em&gt;bad&lt;/em&gt; developer, despite what any TDD fanboys may claim.)  At the end of the day, you haven't quite finished your task, and you let your team lead know that you'll need a little more time before you submit the code.  &lt;/p&gt;

&lt;p&gt;Is there a risk here that you'll come to be seen as something of a "lesser" dev?  Well, to be perfectly frank with you, the answer is "Yes".  If the broader team doesn't embrace TDD, and all they see is that Joe finished a task, estimated at one day, in half a day, and you completed a similarly-estimated task in &lt;em&gt;more than a day&lt;/em&gt;, this could lead some to hold you in less regard.  But honestly, if that's the way your team judges work, then you may need to think carefully about whether this is the right fit for you long term.&lt;/p&gt;

&lt;p&gt;Of course, over time it should become apparent to your colleagues that your methods yield solid code that's prone to fewer reworks. But I also wanna be frank with you:  Some shops will focus, myopically and brutally, on nothing but raw time.&lt;/p&gt;

&lt;p&gt;But I'd encourage you to think about it this way:&lt;/p&gt;

&lt;p&gt;If someone wants me to start developing an endpoint-driven application, but they can't/won't give me the schemas I can expect from those endpoints, and they won't let me develop the endpoints myself, then I'm simply not going to start cranking out code just to satisfy someone who wants to know that I'm coding.  (Even if that coding is &lt;em&gt;blind&lt;/em&gt;.)  I simply won't do it.  And if that causes a problem with my team, I'll find somewhere else to work.&lt;/p&gt;

&lt;p&gt;Similarly, when you're adhering to TDD, you're taking the time to define your own &lt;em&gt;data contract&lt;/em&gt;, upfront, before you ever begin the "real" work of coding.  You shouldn't be afraid to follow that approach.  And if that causes ongoing problems on your dev team, then you really should consider finding a team that will support quality coding.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwvvoz9qnunx4xkhxnyt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwvvoz9qnunx4xkhxnyt.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TDD As A Personal Directive
&lt;/h2&gt;

&lt;p&gt;In conclusion my central point is that, previously, I always saw TDD as a &lt;em&gt;team&lt;/em&gt;-based decision.  We either adopted it for the entire group - or we didn't, and I ignored it altogether.  But it doesn't have to be like that.&lt;/p&gt;

&lt;p&gt;There are many aspects of dev where I've learned, over years of experience, what works best for &lt;em&gt;me&lt;/em&gt; to deliver quality code.  When I encounter those scenarios again, I don't ask someone's permission to write the code in the best way that I know how.  I simply do it.&lt;/p&gt;

&lt;p&gt;TDD can be that type of &lt;em&gt;personal&lt;/em&gt; directive.  Yes, it would be ideal if everyone on your team feels the same.  But if you find that you can write much better code by using TDD, then... do it.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Thank You For Your (Worthless) Comment!</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Thu, 30 Mar 2023 06:13:35 +0000</pubDate>
      <link>https://dev.to/bytebodger/thank-you-for-your-worthless-comment-4o67</link>
      <guid>https://dev.to/bytebodger/thank-you-for-your-worthless-comment-4o67</guid>
      <description>&lt;p&gt;I think one of the things that defines a "programming mindset" is the desire to improve &lt;em&gt;processes&lt;/em&gt; (for example: &lt;em&gt;automating&lt;/em&gt; them).  When a programmer sees manual work being rotely repeated, he has an innate desire to streamline it.  This often takes the form of writing more (or just... &lt;em&gt;better&lt;/em&gt;) code.  But it can manifest in other ways.&lt;/p&gt;

&lt;p&gt;For example, when I noticed that I would often get the same inane questions from recruiters - often, in relation to "opportunities" that I had no desire to pursue - I reworked my LinkedIn profile to speak directly to those questions.  Hopefully, so that I wouldn't need to keep answering them over and over again.  I then built my CV/portfolio site with many of the same objectives in mind.&lt;/p&gt;

&lt;p&gt;Granted, this doesn't &lt;em&gt;stop&lt;/em&gt; the stream of inane questions.  But I &lt;em&gt;have&lt;/em&gt; noticed that it does in fact limit them.  Some recruiters still pay no attention to what's on my LinkedIn profile, or what's on my CV site.  But many others have read what I've written before we even have our initial conversation.  And it's saved me both time and aggravation.&lt;/p&gt;

&lt;p&gt;So, in a similar fashion, I'm writing this article as a way to "automate" the process whereby some "Dev Bro" leaves a snotty and unhelpful comment on one of my articles.  Going forward, I'm not gonna engage the jerks anymore.  My only response will be to drop a link &lt;em&gt;to this article&lt;/em&gt;... and then leave it alone.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4api5dke2fmgzixxse6s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4api5dke2fmgzixxse6s.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dreaded "Comments Section"
&lt;/h2&gt;

&lt;p&gt;There's an old truism about the web.  It was probably coined as far back as the early 90s.  But it's still completely apropos today.  It simply states:&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Never&lt;/em&gt; go into the comments section!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;It seems that the comments section is where the swarthiest sector of the web spends most of their time.  For example, on the website for my local paper, I &lt;em&gt;long ago&lt;/em&gt; realized just how loathsome the comments section can be.  Every alt-right redneck in my southern city feels shamelessly empowered to share their deepest darkest thoughts on our local paper's articles.  I've encountered some of the most racist/sexist/homophobic comments that I've &lt;em&gt;ever&lt;/em&gt; heard after I scrolled just a &lt;em&gt;bit&lt;/em&gt; too far down the page on our local news articles. &lt;/p&gt;

&lt;p&gt;So, on most sites, it's a good rule of thumb to simply close your browser tab or click off the site once you've reached the end of the article and you're starting to see the user-generated feedback.  But why am I talking about this &lt;em&gt;here&lt;/em&gt;, on Dev.to?  Am I claiming that Dev.to's comments are anywhere near that bad?  Thankfully, not at all.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F823v8dva781ajcroc92p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F823v8dva781ajcroc92p.png" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dev.to Community
&lt;/h2&gt;

&lt;p&gt;When I decided to start cranking out articles on Dev.to, I did so, in part, because of the sense of &lt;em&gt;community&lt;/em&gt; that I witnessed while reading the articles of others.  The authors represent a wide range of skill sets, backgrounds, and experience levels.  Of course, I've stumbled across my fair share of articles on this site that I would classify as, ummm... not good.  But I usually have the sense that the vast majority of people on this site are truly trying to &lt;em&gt;help&lt;/em&gt; one another.  (Even if, occasionally, their articles are a bit misguided.)&lt;/p&gt;

&lt;p&gt;I've always been particularly impressed with the quality of the &lt;em&gt;comments&lt;/em&gt; on Dev.to articles.  When some newbie posts an article with glaring flaws, I rarely see the commenters &lt;em&gt;attacking&lt;/em&gt; him.  Yes, they may &lt;em&gt;challenge&lt;/em&gt; him.  They often &lt;em&gt;correct&lt;/em&gt; him.  But on a large majority of comments, it does seem (to me, at least) as though the &lt;em&gt;community&lt;/em&gt; is honestly trying to help each other.&lt;/p&gt;

&lt;p&gt;For this reason, when I began writing my own articles, I made a conscious decision to make every effort to &lt;em&gt;engage&lt;/em&gt; my commenters.  Sometimes this takes the form of a simple "thank you" for their reply.  Occasionally, it becomes a follow-on discussion - something of an "appendix" to the original article.  No, I don't reply to &lt;em&gt;every&lt;/em&gt; comment.  But whenever it feels appropriate (or necessary), I try to acknowledge those who've taken the time to leave comments.&lt;/p&gt;

&lt;p&gt;I can't even count the number of times that someone has challenged something I've written here and their input has led me to reassess and/or reformulate my own views.  Sometimes, commenters simply point out typos or logical flaws in my article.  (When that happens, I typically go back and edit the article to correct the error - after leaving a note thanking the commenter for the insight.)  Other times, commenters have shown me really cool new ways to accomplish something - methods that I'd completely overlooked in the original article.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fhw9v1hjqdkqs9jt0jf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fhw9v1hjqdkqs9jt0jf.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Malcontents and Dev Bros
&lt;/h2&gt;

&lt;p&gt;This doesn't mean that &lt;em&gt;every&lt;/em&gt; comment is helpful.  Nor does it mean that &lt;em&gt;all&lt;/em&gt; comments are left in the spirit of "community".  Dev.to couldn't possibly enforce any kind of sweeping "don't be a jerk" policy.  And if you write even a handful of articles on this site, eventually you'll run into a few of those jerks.&lt;/p&gt;

&lt;p&gt;Of course, one "answer" to this problem would be to simply ignore the comments altogether.  But for the reasons stated above, I believe that would be a sad mistake.&lt;/p&gt;

&lt;p&gt;Another approach is to simply grow a thicker skin.  Blogging is one form of putting yourself "out there".  And whenever you expose your thoughts/feelings/ideas to the teaming cesspool that is The Interwebs, it's inevitable that, occasionally, some snotty little Dev Bro will get his jollies by taking a swipe at you.  &lt;/p&gt;

&lt;p&gt;For the most part, that just comes with the territory.  If you can't handle the occasional jerk putting his oh-so-witty commentary on your articles, then... don't write articles for public consumption.  And to be clear, I practice this approach of "skin thickening" on a near-daily basis.  At this point in my blogging life, and at this point in my overall career, I no longer have "skin".  I have a tough, leathery &lt;em&gt;hide&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I will also freely acknowledge that my particular style can sometimes &lt;em&gt;invite&lt;/em&gt; the Dev Bros to sharpen their knives.  I'm &lt;em&gt;opinionated&lt;/em&gt;.  I make bold assertions.  I enjoy calling out the many different flavors of &lt;em&gt;effery&lt;/em&gt; that I've encountered over the last quarter century.  The articles I write, while not &lt;em&gt;obscene&lt;/em&gt;, are not designed to be presented, verbatim, in a corporate board room.  And when I write in such a fashion, a certain subset of malcontents feels empowered to showcase their Keyboard Commando skills.  And when they do, I make every attempt to simply ignore those jerks.&lt;/p&gt;

&lt;p&gt;Nevertheless, every so often I feel compelled to engage one of them.  And that's why I'm writing &lt;em&gt;this&lt;/em&gt; article.  Consider this my "final word" on any Neanderthal who thinks he's gonna raise himself up by taking me down a notch.&lt;br&gt;
&lt;br&gt;&lt;br&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faj17a8uxs4ytszixfmne.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faj17a8uxs4ytszixfmne.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ohhh... The Delicious Irony!
&lt;/h2&gt;

&lt;p&gt;One of the funniest aspects of these Dev Bros is their utter inability to grasp the irony that's often present in their own comments.  I've covered many different topics on this site.  But if you read even a handful of my articles, you may notice one theme that pops up over and over again.  &lt;/p&gt;

&lt;p&gt;Often, I'm not railing so much against any particular piece of tech, or any particular aspect of coding life.  Instead, I'm railing against &lt;em&gt;the jerks who can't discuss such things in a rational, professional manner&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Like... maybe you love TypeScript.  And you're convinced that our next project should be written in TypeScript - and &lt;em&gt;not&lt;/em&gt; JavaScript.  OK.  That's fine.  I may not entirely agree with you.  But I'm more-than-capable of having a rational discussion with you about it.  In the course of that discussion, you can present your case.  I can present mine.  We can talk about the pros-and-cons of either approach.  We can loop in other team members to gather their feedback on it.  And at the end of the day, we can come to some sort of consensus on a logical approach.&lt;/p&gt;

&lt;p&gt;And when I say "logical approach", that's not a snide code word for &lt;em&gt;my preferred solution&lt;/em&gt;.  Just a few months ago, at Amazon, I had this exact same debate with another senior dev on our team.  He wanted to use TS.  I wanted to use JS.  We hashed it out.  We talked to the rest of the team.  And you know what we decided on?  We decided to use TS.  And guess what???  I was &lt;em&gt;fine&lt;/em&gt; with it!&lt;/p&gt;

&lt;p&gt;But when some Dev Bro leaves a nasty comment on your article, he's "outing" himself as one of those jerks who's incapable of having this kind of rational conversation.  Not that he cares, of course.  He only cares about feeling like he's just put you in your place.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbn9tegtzk3q71rtq3nn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbn9tegtzk3q71rtq3nn.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Smarmy Tech Douchebags
&lt;/h2&gt;

&lt;p&gt;At this point, you may be thinking:&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;OK, fine.  There are some idiots who put snotty comments on blogs.  But why are you writing an article on a tech/programming website, about &lt;em&gt;commenters&lt;/em&gt;???&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;To be fair, you don't have to be in software development to experience jerks in your life.  Douchebags exist in every industry and in every corner of our daily lives.  But I'm a firm believer that software development &lt;em&gt;fosters&lt;/em&gt; a certain outsized population of douchebags.&lt;/p&gt;

&lt;p&gt;No, I'm not claiming that &lt;em&gt;all&lt;/em&gt; programmers are jerks.  The vast majority of my past-and-present colleagues are very nice people.  Smart.  Funny.  Genuinely interested in doing a good job and getting along with their coworkers.  But I do honestly believe that, if we woke up tomorrow and every "jerk" was painted neon green, there'd be a higher percentage of neon green people in software engineering than you'd find in many other career fields.&lt;/p&gt;

&lt;p&gt;Software development has a way of &lt;em&gt;rewarding&lt;/em&gt; douchebags.  You see, programmers are &lt;em&gt;problem solvers&lt;/em&gt;.  And once you've solved enough problems on enough critical projects, it's easy to fall into the mindset that you've got all the answers.  It fosters mindsets like these:&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"I used to work on an Angular project that was an absolute nightmare.  And now &lt;em&gt;you&lt;/em&gt; want to use Angular??  Mannn... you must be an idiot."&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"I've been doing this stuff &lt;em&gt;for decades&lt;/em&gt;.  And now the &lt;strong&gt;New Guy&lt;/strong&gt; thinks he can just step in with a better suggestion on how to solve this problem?  Give me a friggin break..."&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"You've done &lt;em&gt;decades&lt;/em&gt; of work with SOAP and REST, but you've never used GraphQL?  Then there's obviously no way you could work on &lt;em&gt;this&lt;/em&gt; team."&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Oh, you didn't fit well with your previous team/employer?   Hehehe...  Sounds like &lt;em&gt;you&lt;/em&gt; must be the problem!"&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"I know why you're not a fan of pair programming.  Cuz you don't want another dev to see that you suck."&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"I wrote that solution in an hour.  It took you &lt;em&gt;two&lt;/em&gt; hours??  Sounds like you're just not cut out for this team."&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, I could go on (and on, and on...), but you probably get the point.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiay98u43q1a2wo5zj8bk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiay98u43q1a2wo5zj8bk.png" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Subspecies
&lt;/h2&gt;

&lt;p&gt;When someone leaves a nasty comment on your blog, they don't realize it, but they're usually signaling that they belong to one (or more) of these nasty subspecies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Fanboy&lt;/strong&gt; - They love Package X.  You've never used Package X.  Or maybe, you prefer Package Y.  So of course, you're stoooopid.  This can also apply to broader dev practices.  Like, they love TDD.  You haven't used TDD.  Or you have critiques of TDD.  So again... you're stoooopid.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Corporate Apologist&lt;/strong&gt; - You didn't have a good experience working for Company X.  You write about your negative experience, but no matter how you explain the scenario, everything that went wrong was obviously &lt;em&gt;your&lt;/em&gt; fault.  And if you weren't such a crappy developer, you would've done just fine in your previous role.  You can describe a situation where you delivered a bug-free product that went live &lt;em&gt;five minutes&lt;/em&gt; after the expected deadline, and that your employer responded by caning you until you fell into a bloody coma, and The Corporate Apologist will tell you that a "real" developer would've had the solution deployed on-time and that you're just not fit to work on software.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Code Nazi&lt;/strong&gt; - There's one way to code - and that's &lt;em&gt;exactly&lt;/em&gt; how The Code Nazi does it.  If your code doesn't mirror his, you don't know what you're doing and you're not fit to work on his team.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Time Cop&lt;/strong&gt; - In The Time Cop's world, there are two classes of problems.  There are "easy" problems - meaning, problems that &lt;em&gt;he's already solved before&lt;/em&gt;.  And now he can crank out the solution with incredible speed.  And then there are "hard" problems - which are just... problems that he hasn't run into before.  If it's an "easy" problem, then you're expected to code the solution &lt;em&gt;in the time that it would &lt;strong&gt;now&lt;/strong&gt; take him to do the same thing&lt;/em&gt;.  If you take longer to solve the problem (even if it &lt;em&gt;originally&lt;/em&gt; took him DAYS to solve it), you're not good enough to code on his team.  It doesn't matter if it took him six hours to code his first binary tree search.  Now that he can do it in 30 minutes, he expects that any "quality" coder should have already encountered the problem, and should be able to do it in 30 minutes as well.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Benchmark Troll&lt;/strong&gt; - He once spent an entire weekend running a massive series of performance tests on &lt;code&gt;for()&lt;/code&gt; loops versus &lt;code&gt;.forEach()&lt;/code&gt;.  And now that he knows that &lt;code&gt;for()&lt;/code&gt; is 0.2379% faster, you're an absolute idiot if you ever use &lt;code&gt;.forEach()&lt;/code&gt;.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Speed Reader&lt;/strong&gt; - He's a &lt;em&gt;busy&lt;/em&gt; man.  He's incredibly important!  So important, in fact, that he can't be bothered to take the time to &lt;em&gt;read&lt;/em&gt; your article.  Which is fine, but curiously enough, he seems to have plenty of time to &lt;em&gt;comment&lt;/em&gt; on your article and, in a display of sheer arrogance, &lt;em&gt;correct&lt;/em&gt; your article.  It doesn't matter that he merely skimmed the first 7% of the article.  He now feels compelled to write up a "correction".  In fact, sometimes The Speed Reader will boldly acknowledge, at the beginning of his comment, "I wasn't able to read most of your article, &lt;em&gt;but&lt;/em&gt;...".&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Snarkster&lt;/strong&gt; - You've written a 10,000-word magnum opus on a new coding technique involving React Hooks.  Not only have you explained the concept in excruciating detail, but you've also laid out numerous coding samples, and you've even linked to several working CodePens that demonstrate your approach.  Because he's so epically enlightened, The Snarkster leaves a single mind-expanding comment like, "Wow.  This is ugly." &lt;code&gt;&amp;lt;SlowClap/&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Opinionator&lt;/strong&gt; - You've written a pure &lt;em&gt;opinion&lt;/em&gt; piece.  You've gone to great lengths to make it clear that this is just your &lt;em&gt;opinion&lt;/em&gt;.  You've even admitted, numerous times in your article, that you may not have all the info and there's room for competing &lt;em&gt;opinions&lt;/em&gt;.  Despite all of this, The Opinionator still feels compelled to drop his comment stating that your opinion is... stoooopid.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Dogmatist&lt;/strong&gt; - You've written an extensive article on a new way to do two-way data binding in JavaScript.  You may have even acknowledged that two-way data binding isn't everyone's "cup of tea".  But for those who want to pursue it, here's one approach you can take.  The Dogmatist absolutely &lt;em&gt;must&lt;/em&gt; comment to let you know that two-way data binding is &lt;strong&gt;BAD&lt;/strong&gt; and you should be kicked off the interwebs for even having the gall to propose such an approach.  He won't give you one iota of constructive feedback on the actual &lt;em&gt;details&lt;/em&gt; of what you've outlined.  He's just gonna browbeat you for being stoooopid enough to even &lt;em&gt;suggest&lt;/em&gt; the idea.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Entertainer&lt;/strong&gt; - The Entertainer paid a whopping $0.00 for the privilege of reading your article.  And if he's not thoroughly &lt;em&gt;entertained&lt;/em&gt;, he's gonna let you know.  He'll be quick to label your article as "clickbait".  He'll whine about how boring your article is (as though he was strapped to a chair and &lt;em&gt;forced&lt;/em&gt; to read it).  The one thing he absolutely will &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; do is provide any kinda substantive feedback on the &lt;em&gt;content&lt;/em&gt; of your article.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Last Senior&lt;/strong&gt; - If The Last Senior isn't tickled pink with your article, he'll cough up one (and only one) retort:  He'll call you a "junior dev".  He has a massive stamp on his desk that says, "JUNIOR".  When he decides that your article doesn't meet his Holy Standards, he literally mashes the stamp against his own monitor.  Then he sits in the dank basement of his mom's house, laughing uncontrollably for the next 45 minutes, because he's in awe at how he massively &lt;strong&gt;PWND&lt;/strong&gt; you by calling you a "junior dev".  The whole escapade concludes when he posts the screenshots of his &lt;em&gt;sweet dig&lt;/em&gt; on 4Chan.  When he's not branding inadequate bloggers as "juniors", he spends the rest of his time repeatedly checking his DMs, waiting for that magical moment when Dan Abramov finally agrees to hang out with him.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is far from an exhaustive list.  But again, you probably get the point.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fetc16bo8pmhouq6emwyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fetc16bo8pmhouq6emwyv.png" alt="Image description" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Just... Don't Be A Jerk
&lt;/h2&gt;

&lt;p&gt;You may have heard before that, before you say &lt;em&gt;anything&lt;/em&gt;, you should always ask yourself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is it &lt;em&gt;true&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;Is it &lt;em&gt;kind&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;Is it &lt;em&gt;necessary&lt;/em&gt;?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The defining feature of a Dev Bro is that they &lt;em&gt;never&lt;/em&gt; go beyond point #1.  (And sometimes, they don't even make it &lt;em&gt;that&lt;/em&gt; far.)&lt;/p&gt;

&lt;p&gt;There are a lotta ways to benefit from the Dev.to community.  Some people just &lt;em&gt;lurk&lt;/em&gt;.  And you know what?  That's &lt;em&gt;fine&lt;/em&gt;!  Some people write their own articles - although no one's forcing you to go that far.  And of course, you can always comment, if you're so inclined.  &lt;/p&gt;

&lt;p&gt;And I'm not trying to tell you that all of your comments must be sugar-coated.  Occasionally, someone writes something that just really &lt;em&gt;needs&lt;/em&gt; to be... challenged.  There's nothing wrong with that.&lt;/p&gt;

&lt;p&gt;But if your "challenging" comment can't be bothered to at least &lt;em&gt;consider&lt;/em&gt; those three questions, then you're not contributing anything at all.  You're just screaming to the Dev.to community that you're an asshat.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>dogma</category>
      <category>codequality</category>
    </item>
    <item>
      <title>What It Was Like To Code For Amazon (Conclusion)</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Mon, 27 Mar 2023 06:01:46 +0000</pubDate>
      <link>https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-conclusion-3468</link>
      <guid>https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-conclusion-3468</guid>
      <description>&lt;p&gt;(You can read Part 1 of this article here: &lt;a href="https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-1-5034"&gt;https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-1-5034&lt;/a&gt;.  And Part 2 here: &lt;a href="https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-2-5aon"&gt;https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-2-5aon&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;If you've read any of the first two articles from this series, you already know that my Amazon experience was... suboptimal.  But the first thing I have to acknowledge is that I don't actually know what it's like to code for Amazon &lt;em&gt;in general&lt;/em&gt;.  In fact, even if you've coded for Amazon in the past, or even if you're coding for them &lt;em&gt;now&lt;/em&gt;, you don't know what it's like to code for them &lt;em&gt;in general&lt;/em&gt;.  The company's far too big and there are far too many devs strewn across myriad teams and locations for any single person to say, with authority, exactly what the &lt;em&gt;overall&lt;/em&gt; dev experience is like.&lt;/p&gt;

&lt;p&gt;In a company that large, all you can really do is assess your own experience.  Some people may have had experiences similar to mine - or worse, even.  But I'm also certain that some Amazon coders are perfectly happy there.  It all depends, to some extent, on exactly which team/group you worked within, who exactly you worked for/with, and of course, what &lt;em&gt;you&lt;/em&gt; brought to the experience.&lt;/p&gt;

&lt;p&gt;But while I can't paint a broad, definitive picture of exactly what it's like for &lt;em&gt;anyone&lt;/em&gt;, in &lt;em&gt;any&lt;/em&gt; Amazon team/group, I did see enough to draw some curious conclusions.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzzsj17dy4oht146cot3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzzsj17dy4oht146cot3.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lip Service To "Principles"
&lt;/h2&gt;

&lt;p&gt;Amazon constantly touts their "Leadership Principles".  They ask you about them when you're interviewing.  They talk about them in company meetings.  On the surface, at least, they pour a lot of effort into these principles.  (If you're curious, you can see them all here: &lt;a href="https://www.amazon.jobs/content/en/our-workplace/leadership-principles" rel="noopener noreferrer"&gt;https://www.amazon.jobs/content/en/our-workplace/leadership-principles&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Unfortunately, a lot of this emphasis is empty talk.  (I know, I know.  A megacorporation that doesn't always live up to its own stated ideals.  &lt;em&gt;SHOCKING!!!&lt;/em&gt;)  I could go through them one-by-one and nitpick them based upon my short tenure there.  And my perspective is, undoubtedly, biased by my own negative experiences and my own (admittedly brief) tenure.  But in my experience, the most glaring example of a completely-failed "principle" is this:&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Have Backbone; Disagree and Commit&lt;/strong&gt;&lt;br&gt;Leaders are obligated to respectfully challenge decisions when they disagree, even when doing so is uncomfortable or exhausting. Leaders have conviction and are tenacious. They do not compromise for the sake of social cohesion. Once a decision is determined, they commit wholly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;I saw so many examples that made this principle an outright joke that I can't even list them all here.  And I'm not just talking about &lt;em&gt;my&lt;/em&gt; experience.  I'm talking about things I witnessed in &lt;em&gt;other&lt;/em&gt; areas of the organization, and things I was told directly by &lt;em&gt;other&lt;/em&gt; employees.&lt;/p&gt;

&lt;p&gt;I witnessed so many instances where people were simply afraid to speak up.  I sat in meetings where no one but the "talking head" dared utter any kind of objection.  And when they &lt;em&gt;did&lt;/em&gt; bother to raise concerns, I also saw where those concerns were bulldozed because there was no alternative that pleased management.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej811qymy5rszxn3cwxz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fej811qymy5rszxn3cwxz.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Telling Observation
&lt;/h2&gt;

&lt;p&gt;When I wrote this article about working at Amazon (&lt;a href="https://dev.to/bytebodger/what-its-like-to-code-for-amazon-4nke"&gt;https://dev.to/bytebodger/what-its-like-to-code-for-amazon-4nke&lt;/a&gt;) a senior dev from an entirely different part of the company reached out to me on Slack.  He praised the article, thanked me for writing it, and said he was glad to see that I was getting along nicely.&lt;/p&gt;

&lt;p&gt;I thanked him for his feedback.  But I also told him that, in the time since I wrote the article, I'd run into some very difficult situations.  (I didn't deluge him with the full, insanely-long story of everything that had happened.  I just gave him the high-level bullet points.)  His response was very telling.&lt;/p&gt;

&lt;p&gt;He was Australian.  He told me that, in his previous job, there were many times when the dev team would be discussing some particular bit of an application that had already been built.  And frequently they would find themselves saying to each other, "Yeah... this is all a bit crap, isn't it?"&lt;/p&gt;

&lt;p&gt;But he also told me that, when he came onboard at Amazon, he had very similar problems.  Because, for a good bit after he was hired, no one wanted to hear any kinda dissenting opinions - even if they were only "dissenting" as a means to talk out the problem and to (hopefully) come to a better solution.  &lt;/p&gt;

&lt;p&gt;His specific advice was to &lt;em&gt;lay low&lt;/em&gt; for a good while.  Don't say much.  Just kinda "go along" with whatever was being dictated to you.  And then, only after you've been onboard for a good bit, maybe possibly speak up about a few targeted things.&lt;/p&gt;

&lt;p&gt;To be clear, I &lt;em&gt;get&lt;/em&gt; this.  I'd be the first one to tell you that no one wants the Brand New Guy to show up, on Day 1, and immediately tell everyone that they've been doing crappy work.  And that the legacy app is shite.  And that all of their current practices should be thrown out the window.&lt;/p&gt;

&lt;p&gt;But there's a difference between being an arrogant know-it-all versus just being... a humble - but confident - member of the team.  Sometimes some of the best suggestions come &lt;em&gt;from the new guys&lt;/em&gt;.  Because everyone else has grown accustomed to everything as "the way it's always been done".  As long as the New Guy isn't a cocky jerk, there's a lot of value in seeing how someone views the situation with a fresh set of eyes.&lt;/p&gt;

&lt;p&gt;That's what &lt;strong&gt;Have Backbone; Disagree and Commit&lt;/strong&gt; is supposed to be about.  If you see something that seems "off"... say something.  Talk about it with your colleagues.  Or your manager.  Or your stakeholders.&lt;/p&gt;

&lt;p&gt;Sometimes, when you raise those concerns, you'll be "voted down".  &lt;em&gt;And that's fine.&lt;/em&gt;  Other times, you may find that people actually &lt;em&gt;agree&lt;/em&gt; with you - but there are other practical reasons why it will continue to be done that way.  And again - &lt;em&gt;that's fine&lt;/em&gt;.  But it's far healthier to at least have those conversations, rather than being afraid that you'll be labeled as a malcontent merely because you raised reasonable concerns.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjg7b9j8lhi8lez6lbyn4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjg7b9j8lhi8lez6lbyn4.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Big Brother Mentality
&lt;/h2&gt;

&lt;p&gt;Here's something that I encountered multiple times at Amazon.  And I found it to be a bit... disturbing.&lt;/p&gt;

&lt;p&gt;I'd be chatting with someone on Slack about something that seemed "off".  Maybe it was about a project.  Or about a particular person.  Or even about the company in general.  And in these scenarios, with multiple different people, the Slack conversation would end when the other person typed this:&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Maybe we should delete this Slack conversation?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;Now to be clear, we weren't talking about bombing the CEO's house.  We weren't calling anyone an asshole.  In fact, we weren't discussing anything in those Slack threads that I woulda been afraid to say to anyone else, directly to their face.  We were just discussing problems that we'd run into, and potentially how to fix them.&lt;/p&gt;

&lt;p&gt;And yet, on numerous occasions, my Slack counterpart would close the conversation by suggesting &lt;em&gt;that we delete the thread&lt;/em&gt;.  Think about that...  Honestly, every time I encountered it, it felt rather &lt;em&gt;chilling&lt;/em&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F894lzqjqt3kucahmwzpx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F894lzqjqt3kucahmwzpx.png" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Blatant Backstabbing
&lt;/h2&gt;

&lt;p&gt;After coding for a quarter century, I've lost track of the number of coworkers who simply didn't like me.  Work at enough companies, with enough colleagues, and it's inevitable that some people simply won't "take" to you.  But that's not what I'm talking about here.&lt;/p&gt;

&lt;p&gt;Despite all the interpersonal conflicts I've navigated throughout my career, there is only &lt;em&gt;one&lt;/em&gt; company where I've experienced open backstabbing.  And, yes, that company was Amazon.&lt;/p&gt;

&lt;p&gt;When I say "backstabbing", I'm not referring to someone saying that I'm a jerk (take a number - it's a &lt;em&gt;long&lt;/em&gt; line).  Nor am I referring to someone badmouthing my code, or my deliverables, or anything about my work effort.  I'm specifically talking about someone saying, &lt;em&gt;to my face&lt;/em&gt;, that I'm doing great work.  Then turning around, whenever a project suffers from &lt;em&gt;any&lt;/em&gt; kinda setback, and telling everyone else that I've screwed everything up.&lt;/p&gt;

&lt;p&gt;Throughout my career I've had people tell me, to my face, that they thought I really screwed something up.  To be honest, once you get past the raw emotions of those moments, sometimes those interactions can end on an extremely positive note.  But I've never been anywhere else where someone told me one (extremely supportive) thing to my face, and then told someone else (in senior management) the exact opposite when I wasn't there.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnq4dry69bt0t88uws9aa.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnq4dry69bt0t88uws9aa.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend Myopia
&lt;/h2&gt;

&lt;p&gt;The vast majority of Amazon's software engineers specialize in &lt;em&gt;backend&lt;/em&gt; development.  (Specifically, Java.)  And there's nothing wrong with that.  But the company's overall view on frontend development seems to be mired in 2015.&lt;/p&gt;

&lt;p&gt;As a frequent Amazon customer, I'd noticed long before I ever worked there, that their UX was pretty, well... &lt;em&gt;lacking&lt;/em&gt;.  Now I know why.&lt;/p&gt;

&lt;p&gt;To be fair, they successfully drive &lt;em&gt;billions&lt;/em&gt; in revenue through their website.  So I'm not gonna claim that their frontend interfaces are somehow "broken".  And whenever you're operating a site that runs on that kinda epic scale, there are bound to be many considerations that simply don't apply to 99.99% of the other websites that are out there.  &lt;/p&gt;

&lt;p&gt;I'll also acknowledge that there are &lt;em&gt;some&lt;/em&gt; teams in Amazon doing frontend work that utilizes modern standards.  But it's kinda disturbing to see how many teams are oblivious to modern frontend capabilities.  Heck, I even witnessed teams that were &lt;em&gt;hostile&lt;/em&gt; toward any kinda modern frontend approaches.&lt;/p&gt;

&lt;p&gt;In Amazon's internal knowledgebase, some lifelong Java coder wrote a long screed talking about how frontend apps (and modern frameworks - like React) were simply unmanageable and unscalable.  It's quite a long read.  Shortly after I came onboard, I was asking one of our Java devs why we were doing things a certain way.  His response was... to send me that internal article.&lt;/p&gt;

&lt;p&gt;Nevermind the fact that the article in question was written &lt;em&gt;in 2017&lt;/em&gt;.  And nevermind the fact that, &lt;em&gt;on the article itself&lt;/em&gt;, there's long been a disclaimer, right at the top of the article,  stating that most of its contentions are now in doubt.  None of that mattered.  All that mattered was that JS frameworks were "bad" (mmmkay...) and old-skool client-server architecture was "good".&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzif6soc37cr0enlfyp9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzif6soc37cr0enlfyp9.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  A Silver Lining
&lt;/h1&gt;

&lt;p&gt;My last observation comes with a bit of a silver lining (for me, at least).  We all know that Amazon is just one of many Big Tech companies that's jettisoned scores of people in the last six months.  While I understand that layoffs are, in a macro sense, a sad reality of corporate life, Amazon did everything they could to ensure that their internal and external communications around the matter were absolutely clumsy and, quite frankly, unprofessional.  I'm not gonna go through all of that in detail here.  I'm sure you've read the articles in the tech/business news.&lt;/p&gt;

&lt;p&gt;Last month, a new bit of ugliness came from Andy Jassy.  Effective May 1st, they're requiring everyone to be in the office at least three days per week.  I'm sure that, in the final analysis, there will be &lt;em&gt;some&lt;/em&gt; people who manage to get excused from this edict.  But every indication so far is that there will be few exceptions.&lt;/p&gt;

&lt;p&gt;In a sick sort of way, this actually made me feel kinda... &lt;em&gt;relieved&lt;/em&gt;.  You see, I live in Florida.  I'm a remote worker.  When I was hired, my offer specifically stated that I would be a &lt;em&gt;remote worker&lt;/em&gt;.  There were others on my team working under the same pretenses.  And even if all the crap of the last year hadn't happened to me, and even if I was never laid off in January, I'd now be stressed and infuriated by the whole situation.  &lt;/p&gt;

&lt;p&gt;So I guess that, in the final analysis, the last year of "hell" wasn't gonna turn out any better for me, even if I never had any problems on my team and even if I was never booted under any of their layoffs.  As odd as it sounds, that actually makes me feel somewhat "better" about the whole experience.&lt;/p&gt;

&lt;p&gt;I'm not gonna make any attempt to sugarcoat this:  What Amazon's doing now is an outright &lt;em&gt;betrayal&lt;/em&gt; to the scores of people they hired over the last couple of years with the express understanding that they would be remote.  It's also a betrayal to so many of their Seattle workers who made significant life changes (like... moving &lt;em&gt;away&lt;/em&gt; from Seattle to other parts of the country) because they were given &lt;em&gt;repeated assurances&lt;/em&gt; that they would not be forced to come back to the office.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu09cc3i73pxxknctnztq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu09cc3i73pxxknctnztq.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Moving On...
&lt;/h1&gt;

&lt;p&gt;I've put 112 articles on this site (so far).  I wrote all of the others to, hopefully, spread knowledge, learn from the Dev.to community, and foster discussion.  This little series of my-life-at-Amazon articles was the first time that I ever wrote anything here that was &lt;em&gt;not&lt;/em&gt; for those purposes.  I wrote these last three articles &lt;em&gt;for me&lt;/em&gt;.  As I stated in Part 1, this has basically been my self-administered therapy - a way for me to yell into the void about crap that I experienced over the last year.&lt;/p&gt;

&lt;p&gt;That being said, this (not so) little tale is not a tragedy.  Far from it.  I'm currently evaluating one very-solid offer from a potential employer.  I expect to receive a few other solid offers in the next coupla days.&lt;/p&gt;

&lt;p&gt;The simple fact is that, regardless of where I'm working next month, and regardless of what anyone on here thinks about my Amazon tale - I'll be fine.  Beyond fine, in fact.&lt;/p&gt;

&lt;p&gt;As you've no-doubt surmised from these three articles, there are absolutely some aspects of my Amazon experience that still feel crappy as hell.  And there was a period, mostly from November 2022 through January 2023, that all of this took a serious toll on my mental and physical health.  &lt;/p&gt;

&lt;p&gt;But you know what?  That passes.  Life goes on.  And I'll be pissing people off at some new company before you know it.&lt;/p&gt;

&lt;p&gt;Take care!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>What It Was Like To Code For Amazon (Part 2)</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Sun, 26 Mar 2023 18:46:02 +0000</pubDate>
      <link>https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-2-5aon</link>
      <guid>https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-2-5aon</guid>
      <description>&lt;p&gt;(You can read Part 1 of this article here: &lt;a href="https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-1-5034"&gt;https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-1-5034&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Everyone was called to Seattle (FWIW, I live in Florida) for a big onsite meeting from October 17th to the 21st.  The purpose was for a team-building event.  But while we were all there it was a natural time to assess the current state of our almost-finished Big Project.&lt;/p&gt;

&lt;p&gt;Given the myriad of headaches that I explained in Part 1, the original launch date of October 4th had been pushed to November 1st.  My manager, Hardik, had communicated this new date to us repeatedly.  But when we had our first onsite meeting on October 17th, he immediately stated that the project would be deployed &lt;em&gt;that week&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;When I brought up the fact that this hadn't even been thoroughly tested in the LLEs, he said, "That's OK.  We can test it &lt;em&gt;in production&lt;/em&gt;."  Yes, that's right.  Our manager was openly advocating for the feature - which had taken two months to develop - to be tested in production.  This is the same manager who'd freak out and want everything rolled back if even the smallest bug was found in LLEs.  But due to the deadlines he was facing, he was perfectly happy to deploy this package with the assumption that it would be tested &lt;em&gt;in production&lt;/em&gt;.  I was... not happy.&lt;/p&gt;

&lt;p&gt;To be clear, when I say that I was "not happy", I don't mean that I was yelling or cursing at anyone.  I wasn't trying to "fight" anything that we were trying to complete.  But neither was I gonna sit in our team meetings and &lt;em&gt;agree&lt;/em&gt; with his test-in-production edict.  Nor was I gonna sit silently when he openly asked each one of us whether we thought it was ready to be deployed.  I told him, in direct but professional terms, that this was not a good idea.&lt;/p&gt;

&lt;p&gt;I wasn't the only one who objected.  Other devs with far more experience on the team indicated that this approach was... problematic, to say the least.  But it was also painfully clear that they were choosing their words &lt;em&gt;very carefully&lt;/em&gt;.  They knew what happens when you speak up.&lt;/p&gt;

&lt;p&gt;This problem was exacerbated by Hardik's management tendencies.  Whenever we were in meetings and he wasn't getting the answers he wanted, he'd keeping asking the same questions over and over again until everyone either agreed (through exhaustion) or simply shut up.  And as soon as everyone was either browbeaten into agreement or had just decided to bite their lip, he took that as tacit approval from the team.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foirsbr6pqmhn2meagllx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foirsbr6pqmhn2meagllx.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Ray Of Sunshine... Blocked
&lt;/h2&gt;

&lt;p&gt;During that week in Seattle, they also announced that our team would be split in two.  There was a new manager, Chandana, and I'd be reporting to her in a few weeks.  It's probably obvious that I saw this as a great relief.&lt;/p&gt;

&lt;p&gt;I went back to Florida, we launched The Project From Hell, and everything seemed to be getting back to normal.  But in the second week of November, which also happened to be Hardik's &lt;em&gt;last week as my manager&lt;/em&gt;, he called a one-on-one meeting with me.  In that meeting, he explained that I was being put under a 90-day Performance Improvement Plan (PIP).  I was... &lt;em&gt;floored&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;First of all, the idea that you'd put someone under a PIP &lt;em&gt;one week before they're moved to another team&lt;/em&gt; is absolute crap.  There are certain &lt;em&gt;tangible&lt;/em&gt; infractions that call for a PIP, regardless of the timing.  Like, for example, a sexual harassment accusation.  Sometimes, you can be written up for something technical, like introducing a change that breaks production.  But this scenario was just downright... &lt;em&gt;petty&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I wasn't the only one who thought this.  In the pending re-org, we'd been moved under a new director.  I had a number of great discussions with our &lt;em&gt;previous&lt;/em&gt; director, related to this PIP situation.  He agreed with me that it was poor form and highly unusual.&lt;/p&gt;

&lt;p&gt;It was made worse by the fact that Hardik couldn't even cite any tangible examples of where I had supposedly performed poorly.  He also gave me no tangible guidelines for how my improved performance could be measured.  When I pressed him on this, he initially &lt;em&gt;refused&lt;/em&gt; to give me any greater detail.  I eventually had to involve HR, who informed him that he'd have to provide exactly what I was asking for.  But when he finally did, his write-up was riddled with talking points that were &lt;em&gt;verifiably false&lt;/em&gt;.  I'm talking about tangible facts like dates and recorded conversations in which his PIP bullet points were in direct conflict with the data.&lt;/p&gt;

&lt;p&gt;We had a senior architect in our group, Vince, who was &lt;em&gt;above&lt;/em&gt; Hardik.  Vince's blessing was apparently required on this PIP.  So I interfaced with him directly.  When we spoke, he indicated that Hardik wasn't the only one who thought there was a problem with my performance.&lt;/p&gt;

&lt;p&gt;One of the other people who corroborated Hardik's account was Shawn, the tech lead for the project on which I was farmed out many months ago.  I won't repeat that ridiculous scenario in this article - it's all in Part 1.  But it was pretty deflating to know that his input was taken on this - when he repeatedly &lt;em&gt;apologized to me&lt;/em&gt; about the state of his project and told me, verbatim, &lt;em&gt;that they weren't even ready to have a frontend dev on the project yet&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Another person was &lt;em&gt;Andy&lt;/em&gt;.  Yes, the same Andy who repeatedly complained &lt;em&gt;to me&lt;/em&gt; about Hardik's many shortcomings.  The same Andy who told me, before he transferred out of the team, that he'd love to work with me again.  But supposedly, in the single month that transpired between that conversation and this PIP, he'd gone on record as stating that I was somehow a problem.&lt;/p&gt;

&lt;p&gt;Vince himself told me that, when I was in Seattle, he could tell there was a lot of tension between me and Hardik.  And this was part of the reason why he went along with the idea of the PIP.  &lt;em&gt;Of course there was tension!&lt;/em&gt;  Hardik was unilaterally moving up deadlines and openly advocating that we test everything &lt;em&gt;in production&lt;/em&gt;.  He was blatantly bulldozing any objections - and not just from me, but from his other senior team members.&lt;/p&gt;

&lt;p&gt;It was painfully clear to me what had happened.  &lt;em&gt;Someone&lt;/em&gt; had to be the "fall guy" for the fact that the Project From Hell wasn't launched on its original target date.  Guess who that fall guy was??&lt;/p&gt;

&lt;p&gt;I have never felt more blatantly backstabbed in 25 years as a software engineer.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkiifqjinw2ck0i25mm0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkiifqjinw2ck0i25mm0.jpeg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving Forward
&lt;/h2&gt;

&lt;p&gt;For the next month, I resolved to do everything I could to close out that PIP and be The Best Possible Amazon Employee.  I met with my new manager, Chandana, on a near-daily basis.  And from every bit of feedback she ever gave me, she seemed to &lt;em&gt;love&lt;/em&gt; me.  She routinely praised the work I was doing.  She told me that she wanted to get the PIP closed out early - as soon as possible.  She never said or did anything that indicated, in any way, that she had even the slightest problem with my performance.&lt;/p&gt;

&lt;p&gt;She even asked me to directly mentor a junior dev on our team.  There were many, umm, "holes" in his knowledge and he was starting to withdraw.  We started a routine of pair programming.  I also met with him daily to review his work, give him pointers, counsel him on how to improve, and to generally pull him back into the fold.&lt;/p&gt;

&lt;p&gt;I was put on a new project where I had to interface with one of our key stakeholders, a senior marketing director, Ted, in Germany.  He repeatedly told me how happy he was with my work and how I was providing far more value than his contractors.  In fact, I spent a good amount of time bringing his contracting team up-to-speed and correcting mistakes they'd made.&lt;/p&gt;

&lt;p&gt;I also spent copious amounts of time documenting the state of the existing system, and writing detailed proposals to migrate it to a new platform.  During that process, I engaged many other senior individuals both inside and outside of our team to review proposals and find consensus.  I also helped several other marketing managers navigate hard-to-solve issues in our own app.&lt;/p&gt;

&lt;p&gt;I scheduled one-on-one's with all the other members of my team.  In those meetings, I openly told them that I was under a PIP and that I wanted any feedback (critical or otherwise) that would help me to improve myself and my contributions going forward.  Most of those meetings ended with the individuals telling me that they didn't agree with the PIP at all.  &lt;/p&gt;

&lt;p&gt;A few people gave me a handful of minor points to improve upon.  But it was pretty clear that &lt;em&gt;no one on my team&lt;/em&gt; was bothered with me in the slightest.  I talked with Andy's replacement - a guy named Cole.  When I told him that I was feeling pretty worried about the status of my job, he told me directly that he'd be pretty upset if I was released.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsm4jovcczrijh232zlc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsm4jovcczrijh232zlc.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dark Clouds Gathering
&lt;/h2&gt;

&lt;p&gt;Even though I was trying to "keep my chin up", it was still sometimes difficult to keep my head in a positive place.  The news broke in late November that layoffs were coming.  Our new director called a huge "all hands" meeting in which he spewed every lame, evasive bit of "corporate speak" that he could muster.  I didn't speak up at all.  But others did.  And he did nothing at all to answer anyone's questions.&lt;/p&gt;

&lt;p&gt;Chandana informed me that she was going to India for an extended vacation over the holidays.  She told me that, before she left, she wanted to have my PIP &lt;em&gt;closed out&lt;/em&gt;.  Not only was she singing my praises, but she also got Ted to write up all the good work I was doing.  Then she got Vince, the senior architect in our group (and the same one who'd originally put his "blessing" on the PIP) to confirm all the great work I'd done and that he'd heard nothing but positive things about my performance.&lt;/p&gt;

&lt;p&gt;Nevertheless, the time came for her to go to India for three weeks and... my PIP was still in place.  I knew that she'd actively pushed to get it closed out.  I knew that she'd gathered supporting input from the most influential people in our group.  And I knew that she failed.  While she always strove to paint things in the best possible light, I &lt;em&gt;knew&lt;/em&gt; that this was not a good sign...&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwp3ln5lpvk54yq1z0a8n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwp3ln5lpvk54yq1z0a8n.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Great Hookah Incident of Christmas '22
&lt;/h2&gt;

&lt;p&gt;The week before Christmas, after Chandana had already left for India, I was called into a last-minute troubleshooting meeting.  There were probably 10 of us on the call.&lt;/p&gt;

&lt;p&gt;Seeing as how it was &lt;em&gt;last-minute&lt;/em&gt; (I was literally pinged on Slack with a request like, "Hey, can you please jump on this call?  We're trying to figure something out."), I was sitting there at my desk (I work &lt;em&gt;remotely&lt;/em&gt;) puffing on a hookah.  This is nothing new for me.  I often smoke a few hookahs a day while I'm working.  It relaxes me.  I've always enjoyed hookah.&lt;/p&gt;

&lt;p&gt;I'd frequently been in standups, &lt;em&gt;on camera&lt;/em&gt;, smoking a hookah.  No one cared.  In fact, some people had even &lt;em&gt;laughed&lt;/em&gt; about it.  I'd been on calls &lt;em&gt;with my director&lt;/em&gt; while smoking a hookah.  One of the other dev managers actually said to me once, "Ohh, man.  Is that a hookah?"  And when I confirmed that it was, he said that he's from Romania and he couldn't wait to smoke one when he went home.  I was often smoking a hookah during my one-on-one video conferences with Ted, a main stakeholder who had advocated for the (failed) early closure of my PIP.  He joked with me that I looked like a dragon.&lt;/p&gt;

&lt;p&gt;But during this last-minute call that I was dragged onto, apparently &lt;em&gt;someone&lt;/em&gt; else on that call was beside themselves.  I learned, after the fact, that they spent a good chunk of that video conference &lt;em&gt;taking screenshots of me&lt;/em&gt;.  And once the call was finished... they reported me to HR.&lt;/p&gt;

&lt;p&gt;Of course, I didn't know that any of this was happening.  Instead, I got a generic meeting request from someone in HR whom I'd never heard of.  The meeting had no subject.  And I wondered for a bit whether it would be to discuss some aspect of my PIP.&lt;/p&gt;

&lt;p&gt;When I got on the call with them, they told me that someone reported that I was smoking a vape during a video conference.  I was, honestly, pretty dumbfounded.  And confused.&lt;/p&gt;

&lt;p&gt;I made no attempt to deny it.  (Why should I???)  I told her that it wasn't actually a vape.  It was a hookah.  But I also acknowledged that this distinction was probably beside-the-point.  Then I said, "I'm sorry.  I've read &lt;em&gt;all&lt;/em&gt; of Amazon's corporate policies (and there are a &lt;em&gt;ton&lt;/em&gt; of them) and I never saw where there's &lt;em&gt;any&lt;/em&gt; policy against smoking a vape or a hookah during an &lt;em&gt;internal&lt;/em&gt; video call."  She replied that &lt;em&gt;there is no policy against it&lt;/em&gt;.  And that the only "infraction" would be around generic ideas of A) workplace conduct (Yeah... &lt;em&gt;no shit&lt;/em&gt;.  I'm not gonna drag a hookah &lt;em&gt;into the corporate office&lt;/em&gt; and start smoking it.  I'm not &lt;em&gt;stupid&lt;/em&gt;.), and B) general ideas of "professionalism".&lt;/p&gt;

&lt;p&gt;Although I was flabbergasted (and more than a bit annoyed) that I was being "reported" for something that even HR had to admit &lt;em&gt;is not against company policy&lt;/em&gt;, I told her, in no uncertain terms, that I apologized and that it would never ever happen again.  She seemed perfectly fine with this.&lt;/p&gt;

&lt;p&gt;I told her that I'm currently under a PIP and asked if this was gonna impact that assessment.  She said, "&lt;em&gt;No.&lt;/em&gt;  We just have to record that we've talked to you about it."  And... that was it.  The call lasted all of 15 minutes.  She told me there would be no further repercussions from this "incident".&lt;/p&gt;

&lt;p&gt;But I knew better...&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faf9dyw16n29az423t5ol.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faf9dyw16n29az423t5ol.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Waiting For The Axe To Fall
&lt;/h2&gt;

&lt;p&gt;Although HR claimed that the Hookah Incident would have no further impact, I pretty much knew that was complete BS.  Everyone I knew in our team/group was openly telling me that they my work was great and they were advocating for the PIP to be closed out.  But that... didn't happen.  My manager was literally on the other side of the world.  A massive round of layoffs was looming.  Then you add this silly hookah incident to the mix, and, well... I had major fears about how this would play out.&lt;/p&gt;

&lt;p&gt;I lost insane amounts of sleep over the holidays.  I developed a nasty cough which eventually led me to be a mucous-y and bloody mess.  I was afraid I was going to lose my job and there wasn't a damn thing I could do about it.&lt;/p&gt;

&lt;p&gt;Those fears were manifested after everyone came back from the holidays.  I got a Slack message from Vince asking for some background info on this whole Hookah Incident.  So I jumped on a call with him. And the news was... not good.&lt;/p&gt;

&lt;p&gt;He was bothered.  Not with me.  But by the idea that the Hookah Incident was apparently being bandied about as some kinda justification for why I should be tagged for released.  He directly confirmed that he'd been hearing nothing but good things about me.  But our new director was apparently hung up on not only the fact that I was still under a PIP (which everyone wanted closed out - but &lt;em&gt;he&lt;/em&gt; refused to do so), but now, also, I had "an HR complaint".  An HR complaint about something that HR openly admitted &lt;em&gt;is not against any corporate policy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Vince was as supportive as he could be in our call.  And of course, he couldn't give me any direct statement like, "You're gonna be released."  But... I knew.  I &lt;em&gt;totally&lt;/em&gt; knew.&lt;/p&gt;

&lt;p&gt;When Chandana got back from vacation, she was &lt;em&gt;distressed&lt;/em&gt;.  She also could not say anything like, "You're gonna be released."  But she knew.  I knew.  We both knew.  And she wasn't happy about it.  At all.&lt;/p&gt;

&lt;p&gt;My last week at Amazon, I wrapped up every open task on my plate.  Chandana had me do some "transition activities" with our PM and another of the senior devs on our team.  When I met with them, they both asked me, "Why are you doing this?"  I replied, "Because I'm gonna be released next week."  They didn't wanna believe me.  But they knew that they had to absorb whatever handoff info that I could impart to them.&lt;/p&gt;

&lt;p&gt;On the morning of January 18th, I went out for a long breakfast.  I had cocktails.  Why not???  I got back to my desk at about 9:30AM.  (Most of my team is West Coast, so it's not like anyone was expecting me to be online before then anyway.)&lt;/p&gt;

&lt;p&gt;At 10:00AM, I received the email.  (All of the victims at Amazon were laid off via... email.  There was absolutely no human interaction.)  And just like that... it was done.&lt;/p&gt;

&lt;p&gt;In the final installment of this diatribe, I'm gonna outline some of the dystopian aspects of Amazon's corporate culture that I witnessed during my 10 months in the fold.  Stay tuned for Part 3...&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>What It Was Like To Code For Amazon (Part 1)</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Sat, 25 Mar 2023 20:55:27 +0000</pubDate>
      <link>https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-1-5034</link>
      <guid>https://dev.to/bytebodger/what-it-was-like-to-code-for-amazon-part-1-5034</guid>
      <description>&lt;p&gt;Last year I wrote a couple articles about my "Amazon journey".  You can read them here &lt;a href="https://dev.to/bytebodger/how-i-got-hired-at-amazon-3ajl"&gt;https://dev.to/bytebodger/how-i-got-hired-at-amazon-3ajl&lt;/a&gt; and here &lt;a href="https://dev.to/bytebodger/what-its-like-to-code-for-amazon-4nke"&gt;https://dev.to/bytebodger/what-its-like-to-code-for-amazon-4nke&lt;/a&gt;.  My Amazon "career" lasted all of 10 months.  On January 18th, Amazon released 18,000 workers.  And I was one of them.&lt;/p&gt;

&lt;p&gt;I've hemmed-and-hawed over writing this article for a few months.  The first few times I tried to write this, it was &lt;em&gt;wayyyy&lt;/em&gt; too bitter, and it would've come across merely as "sour grapes".  So I scrapped those original drafts.  But now, after having a few months' separation from the Amazon machine... I think it's time.&lt;/p&gt;

&lt;p&gt;I'm gonna be frank here.  This article is basically my own self-administered therapy.  If it doesn't strike you as being "professional" or if you feel like hopping into the comments and deriding me for my opinions, well... I really couldn't care less.  You can write your own blog post about how I'm an idiot, or about how everyone jettisoned from Amazon deserved what they got, or about how this is all just "the way of the world".  But this is &lt;em&gt;my&lt;/em&gt; post.  And I'm gonna explain things exactly as I experienced them.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsul33zk6xs0kig4yewph.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsul33zk6xs0kig4yewph.jpeg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Laying My Cards On The Table
&lt;/h2&gt;

&lt;p&gt;Before I get into details, I wanna be dead-honest about a few key points.  First, there's nothing about &lt;em&gt;my&lt;/em&gt; experience that can be taken as a blanket statement on Amazon as a whole.  The company is &lt;em&gt;huge&lt;/em&gt;.  Their workforce - even after the layoffs - is &lt;em&gt;huge&lt;/em&gt;.  There are still more than a &lt;em&gt;million&lt;/em&gt; Amazon employees.  And even if we filter out all the non-coders, it's still a massive workforce.  So if you worked at Amazon in the past, or if you work there now, your experience may be completely different from my own.&lt;/p&gt;

&lt;p&gt;Second, I can honestly tell you that I was "all-in".  I sincerely hoped that Amazon would be my &lt;em&gt;last&lt;/em&gt; employer.  I really wanted to &lt;em&gt;make it work&lt;/em&gt;.  So it's not like I came onboard at Amazon trying to "make waves".  &lt;/p&gt;

&lt;p&gt;Third, it would be really easy in this situation to point to the company-wide layoffs and insist that my removal had nothing to do &lt;em&gt;with me&lt;/em&gt;.  Afterall, they cut 18,000 people (and they just announced another 9,000 impending layoffs).  So I could easily fall back on the comforting bromide that I was a victim of broader market forces.  But that would be... wrong.&lt;/p&gt;

&lt;p&gt;No one else on my team was released.  I was singled out.  And it caused me an extreme level of mental anguish from November of 2022 through January of 2023.&lt;/p&gt;

&lt;p&gt;So what exactly went wrong?  Well, let's dive into that...&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgl3bn7jppe91eifuctp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgl3bn7jppe91eifuctp.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Living On An Island
&lt;/h2&gt;

&lt;p&gt;In a quarter-century of software engineering, I've never worked at any company where I felt quite like I did at Amazon.  Like I was working &lt;em&gt;on an island&lt;/em&gt;.  I was hired into a team of backend devs who were accustomed to working &lt;em&gt;only&lt;/em&gt; in Java.  And to be clear, that's &lt;em&gt;fine&lt;/em&gt;.  I'm a Java dev myself.  But I was specifically hired to work &lt;em&gt;on the frontend app&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;No one on my team could even tell me how to run our app locally.  &lt;em&gt;No one.&lt;/em&gt;  You may be thinking, "Well... what's so hard about &lt;code&gt;npm start&lt;/code&gt;?"  But you could not run our frontend app with &lt;code&gt;npm start&lt;/code&gt; or &lt;code&gt;yarn&lt;/code&gt; or any other tools that are customary for frontend devs.&lt;/p&gt;

&lt;p&gt;When I came onboard, there were a series of instructions in the repo to tell you how to get the app running.  They did &lt;em&gt;not&lt;/em&gt; work.  At all.  It took me a few &lt;em&gt;weeks&lt;/em&gt; to even figure out how to get the app running in a test environment.  And I had to figure it out by myself, because when I reached out (repeatedly) to other devs on the team to figure out how to make it all run... they were clueless.&lt;/p&gt;

&lt;p&gt;Even when I &lt;em&gt;did&lt;/em&gt; get it running, the "default" configuration was to run everything on an EC2 instance (internally referred to as your &lt;strong&gt;Cloud Desktop&lt;/strong&gt;).  And that may have been fine.  Afterall, I've worked on EC2 instances before.  But the only way to make it run on EC2 was to do a complete compile-and-push of the &lt;em&gt;entire&lt;/em&gt; app - meaning, frontend and backend code - that took &lt;em&gt;13 MINUTES&lt;/em&gt; every time I wanted to test my changes.  &lt;/p&gt;

&lt;p&gt;Everyone else on the team seemed to think that this was just "business as usual".  They couldn't seem to understand why I was exasperated to learn that every single code change would take &lt;em&gt;13 MINUTES&lt;/em&gt; to verify.&lt;/p&gt;

&lt;p&gt;Granted, I did &lt;em&gt;eventually&lt;/em&gt; figure out how to sync my local environment in real-time to the EC2 instance.  But it took me a &lt;em&gt;long&lt;/em&gt; time to work that out.  Once I had the sync running, I could see my changes on the EC2 instance in about 10 seconds.  But I had to work that all out on my own, because none of the existing documentation gave any clue as to how I could make that work.  &lt;/p&gt;

&lt;p&gt;Once I figured this out, I documented all of the steps so that future devs would never need to go through the headache I'd experienced.  But I could already tell that my manager, Hardik, was growing exasperated by the delay before I could write new code efficiently.&lt;/p&gt;

&lt;p&gt;Even with no meaningful guidance, my path to efficient development would've been much smoother if I wasn't working on a Windows machine.  When I was hired, several weeks before my start date, I received an email asking me if I wanted a Mac or a Windows machine.  Although I've worked on Macs, I've always done much more work on Windows (yes, I know, this is unusual), so I simply replied that I'd like a Windows machine.  That was a &lt;em&gt;big&lt;/em&gt; mistake.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All&lt;/em&gt; of the internal Amazon documentation starts from the assumption that you're on a Mac.  Even after I "translated" many of the commands from bash to PowerShell, I still encountered &lt;em&gt;many&lt;/em&gt; roadblocks that were maddening to solve.  There were many command line utilities they expected you to use that simply would not run on a Windows maching.  Although I eventually &lt;em&gt;did&lt;/em&gt; solve everything, after I'd been there for a couple months, I finally said, "Can you guys just send me a Mac?"&lt;/p&gt;

&lt;p&gt;To be fair, they did in fact send me a Mac.  But by that point, I was already seen by Hardik as someone who was lagging behind.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhovshc124zh1xcniy87.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhovshc124zh1xcniy87.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Farmed Out
&lt;/h2&gt;

&lt;p&gt;Once I finally reached a state where I could efficiently code in the environment, I was immediately farmed out to another team on a short-term, high-priority project.  Of course, that project came with a whole other docket of onerous setup requirements.&lt;/p&gt;

&lt;p&gt;I was the only frontend dev working on this new initiative.  When they introduced me to the project, they pointed me to the repo - but it wouldn't even compile.  In fact, I'd get on a conference call with the team lead, Shawn, and it would take him &lt;em&gt;hours&lt;/em&gt; to get the app running locally.  &lt;/p&gt;

&lt;p&gt;When we went through these sessions, Shawn repeatedly apologized to me about the state of the project.  He also told me, on numerous occasions, that they probably weren't even &lt;em&gt;ready&lt;/em&gt; to have a frontend dev working on the project yet.  But I was still expected to crank out frontend code.&lt;/p&gt;

&lt;p&gt;They were building a brand new app.  But the pipeline was configured &lt;em&gt;to only accept ES5-compliant JavaScript&lt;/em&gt;.  When I brought this up to them as a major red flag, they literally couldn't understand why I had any problem writing brand new code, &lt;em&gt;in 2022&lt;/em&gt;, with &lt;code&gt;var&lt;/code&gt;s - and all of the other ancient standards of ES5.&lt;/p&gt;

&lt;p&gt;And those compilation problems didn't go away after the first time that I finally got the app running.  I'd start working the very next day, after changing &lt;em&gt;nothing&lt;/em&gt; in the code, and I'd find that, once again, the app wouldn't compile.  It didn't compile because the backend devs were constantly changing key parameters of the app.  But those parameters were not all checked into a cogent changeset.  So even if the app worked perfectly fine &lt;em&gt;yesterday&lt;/em&gt;, I'd get latest when I started working the next morning and... nothing worked.&lt;/p&gt;

&lt;p&gt;When this happened, I'd get back on a conference call with Shawn, and &lt;em&gt;even for him&lt;/em&gt;, it would still take him &lt;em&gt;hours&lt;/em&gt; to get the latest build to a point where it would simply compile.  He'd still apologize to me about it the whole time.  And he kept telling me that they really weren't even &lt;em&gt;ready&lt;/em&gt; to have a frontend dev working on the code yet.  But I was still working on the project.  And nearly every day I ran into the same kinds of issues.&lt;/p&gt;

&lt;p&gt;Even when I could get the project &lt;em&gt;running&lt;/em&gt;, it was still maddening to figure out exactly what I was supposed to code.  They kept telling me that I had to code for certain variables that would be coming from the backend.  But those backend services weren't anywhere near being completed.  And they couldn't even give me a mockup of what the data was supposed to look like.  I was literally coding blind.&lt;/p&gt;

&lt;p&gt;I'd conference with my regular manager, Hardik, every coupla days.  And every time I told him that this project was a nightmare and that I really shouldn't be on the project at all until they'd figured out their backend issues.  And Hardik &lt;em&gt;agreed&lt;/em&gt; with me.&lt;/p&gt;

&lt;p&gt;I also repeatedly told the team lead, Shawn, that my time would be best spent if I came back to the project a few months later.  And he &lt;em&gt;agreed&lt;/em&gt; with me.  But it took more than a month before I was officially able to beg myself off the project.&lt;/p&gt;

&lt;p&gt;Despite all these issues, that were acknowledged by my regular manager, Hardik, and by the team lead of the secondary project, Shawn, I learned a few months later that I was reported to senior management as being "difficult to work with".  It was an absolute &lt;em&gt;betrayal&lt;/em&gt;.  But I tried not to let it bother me, because by the time that I received this information I was already moved back to my original team.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoclncefp36p4i0t5c52.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoclncefp36p4i0t5c52.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Back On The Reservation
&lt;/h2&gt;

&lt;p&gt;At this point, I'd successfully navigated the insanely-obtuse process of working on my main team's frontend application.  And I'd weathered the nightmare of the temporary project on which I was farmed out.  But it was clear that my manager, Hardik, thought that I was somehow lagging behind.&lt;/p&gt;

&lt;p&gt;He and I had a meeting where he suggested that I should just concentrate on cranking out code for our main app (it's called "Sonar").  He specifically recommended that I focus on trying to get 10 pull requests submitted over the next month.  &lt;/p&gt;

&lt;p&gt;I totally agreed with him and I dove into our "regular" work with aplomb.  In fact, I had more than 10 pull requests submitted &lt;em&gt;in the next week&lt;/em&gt;.  But from that point forward, he continually talked about me as though I wasn't doing much work.&lt;/p&gt;

&lt;p&gt;This situation continued on for several months.  It actually got to the point where I showed him, with &lt;code&gt;git&lt;/code&gt; commits, and pull request history, and completed tickets, that I'd completed more than &lt;em&gt;four times as much work as anyone else on the team&lt;/em&gt;.  But it just didn't seem to register with him.  He'd always talk about me - to my face, and in group meetings - as though I was somehow failing to deliver.&lt;/p&gt;

&lt;p&gt;I wasn't the only one who noticed Hardik's disconnect with reality.  We had a senior architect, Andy, embedded within our team.  He would routinely talk to me on Slack about how frustrated he was with Hardik.  He told me that he'd reported these frustrations to our director.  And he encouraged me to submit a report of my own experiences.  However, I held back from doing so because, at that point, I'd still only been there for about five months and I really didn't think it would be a "good look" for the New Guy to be griping to the director about his manager.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllwciozdag8zf98nzynx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllwciozdag8zf98nzynx.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Captain Rollback
&lt;/h2&gt;

&lt;p&gt;I soon learned that Hardik was also Captain Rollback.  In our codebase, we had a handful of ancient unit tests that were borderline useless.  (Also, fun fact:  No one knew how to run them and they weren't hooked up to the deployment pipeline in any way.)  Even if you could figure out how to run them (I did), they covered such a small part of the app as to be useless.&lt;/p&gt;

&lt;p&gt;There were also significant parts of our app that no one on our team even knew how to use.  So between the worthless test "coverage" and the complete lack of institutional knowledge, the only real way to test your changes was to push them to your EC2 environment and check them manually.  But without sufficient end-to-end knowledge of the app (which &lt;em&gt;no one&lt;/em&gt; had), manual testing was hit-or-miss.&lt;/p&gt;

&lt;p&gt;Perhaps because of these factors, Hardik was Captain Rollback.  Whenever any bug - no matter how trivial - was discovered in a LLE, his first-and-immediate instinct was &lt;em&gt;always&lt;/em&gt; to rollback the code.  Of course, when you've just deployed &lt;em&gt;to production&lt;/em&gt; and you found a bug, I can totally understand this impulse.  Or if you have a production deployment pending in the very near future, I also understand this impulse.&lt;/p&gt;

&lt;p&gt;But if there was &lt;em&gt;any&lt;/em&gt; issue with &lt;em&gt;anything&lt;/em&gt; I'd written - no matter how &lt;em&gt;trivial&lt;/em&gt; the issue - he never asked what it would take to simply &lt;em&gt;fix&lt;/em&gt; the issue.  He immediately wanted to rollback.&lt;/p&gt;

&lt;p&gt;On several occasions, after a bug was found &lt;em&gt;in production&lt;/em&gt;, he wanted to rollback my latest changes &lt;em&gt;in the LLEs&lt;/em&gt;, even though my changes &lt;em&gt;had not yet been deployed to production&lt;/em&gt;.  On other occasions, he wanted to rollback my code, even though the change I'd made had no conceivable connection whatsoever to the observed bug.&lt;/p&gt;

&lt;p&gt;And I wasn't the only one telling him this.  Other devs, with much more experience on the team, would tell him the same thing.  But it didn't matter.  Any observed bug led to an immediate knee-jerk directive from Hardik to rollback &lt;em&gt;my&lt;/em&gt; latest changes.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0ldow7pbmy5wijs67qn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0ldow7pbmy5wijs67qn.jpg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project From Hell
&lt;/h2&gt;

&lt;p&gt;Although I had some ongoing "issues" with Hardik, I was still intent on delivering solid work.  And that "solid work" took the form of a big new project that had to be implemented in Sonar.&lt;/p&gt;

&lt;p&gt;To be clear, this "big new project" didn't really seem like any kinda &lt;em&gt;major&lt;/em&gt; project upfront.  We went through sprint planning and I pointed my tasks as presumably taking several weeks.  I was giving my estimates based on everything I knew about the app (and the newly-required features) at the time.  But there was much that I couldn't have possibly understood about the requirements in the early stages...&lt;/p&gt;

&lt;p&gt;We worked off a continuous deployment model.  And even though &lt;em&gt;my&lt;/em&gt; piece of the project seemed small, it was clear that the entire effort would take a few months.  So when I started planning how to do &lt;em&gt;my&lt;/em&gt; pieces of the project, it was clear that I couldn't just commit them upfront - because if I did, they'd get deployed to production and they would break because the backend pieces hadn't been completed.&lt;/p&gt;

&lt;p&gt;I talked with our architect, Andy, about how to handle this.  After talking through a few options, we both agreed that this should be deployed under a feature flag, so that my new pieces wouldn't break anything before the full project was released.&lt;/p&gt;

&lt;p&gt;Then I asked him, "Can you show me in the codebase where we're already using feature flags, so I can follow the same methodology?"  He replied that there &lt;em&gt;was no&lt;/em&gt; existing feature-flag functionality in the codebase.  And that was fine.  I set about &lt;em&gt;building&lt;/em&gt; a new feature-flag system.  But of course, that set back my original estimates.&lt;/p&gt;

&lt;p&gt;Granted, I &lt;em&gt;copiously&lt;/em&gt; communicated this to the team every step of the way.  I created new tickets to track the feature flag development.  I repeatedly advised the team about the revised timelines during nearly every standup.  I also built the feature-flag functionality to be "universal", so that it was highly configurable and could be used for any-and-all conditional features that may be needed in Sonar in the future.  Nevertheless, Hardik was not pleased.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cg1lutkjrrjb4fee0rd.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6cg1lutkjrrjb4fee0rd.jpeg" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Shifting Data Models
&lt;/h2&gt;

&lt;p&gt;Once the feature-flag functionality was in-place, I set about coding the original requirements for the project.  The frontend functionality seemed, on the surface, to be pretty simple.  Basically, we needed to account for a few new values coming from the API.  Originally, I was led to believe that &lt;em&gt;someone else&lt;/em&gt; would be altering the API.  But I eventually learned that I would need to do it myself.  Which was... fine.  But that was never in my original estimates.&lt;/p&gt;

&lt;p&gt;So I created new tickets to track the updating of our APIs.  And I communicated this all to the team, &lt;em&gt;repeatedly&lt;/em&gt;, during standups.  Then I coded the Java updates to deliver the values that were needed.&lt;/p&gt;

&lt;p&gt;Only &lt;em&gt;after&lt;/em&gt; I'd done this, Andy informed me that my data model wouldn't "work".  It's hard to explain here, but suffice it to say that, in their odd data model, I instead needed to &lt;em&gt;infer&lt;/em&gt; the values based on a very convoluted set of &lt;em&gt;other&lt;/em&gt; variables that would be returned from the API.  Of course, I had no way of knowing that when I made my original estimates.&lt;/p&gt;

&lt;p&gt;After I'd already coded a new Java API to handle what I presumed would be the new variables, Andy informed me that he would be spinning up his own set of APIs that I'd consume.  Which meant that my previous Java API work was wasted.  It also meant that the frontend code I'd written, which assumed it would be receiving the values I'd coded into the API, had to be completely rewritten.  He was also unable to give me any kinda putative mock data that I could use to write new frontend code.  In other words, I was stuck waiting on him to show me what the new data would look like.&lt;/p&gt;

&lt;p&gt;I communicated all of this to the team, &lt;em&gt;repeatedly&lt;/em&gt;, during standups, and I did what little frontend coding I could in lieu of any knowledge of the data model.&lt;/p&gt;

&lt;p&gt;During this same time, Andy continued to tell me how frustrated he was with Hardik's crappy management.  In fact, one day he scheduled a one-on-one meeting with me where he told me that he was transferring to another team.  During this meeting, he also told me that, "If you'd ever like to move to another team, just let me know.  I'd be happy to work with you again."&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpt4xcc8z8e863xse9iz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdpt4xcc8z8e863xse9iz.png" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deadlines Uber Alles
&lt;/h2&gt;

&lt;p&gt;We were supposed to deliver this new functionality in the middle of October.  We'd previously planned to have the functionality in our LLEs right around October 1st so we could begin testing.  I finally received a mockup of the data model against which I needed to code my features &lt;em&gt;on Friday, November 30th&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;By Monday, October 3rd, Hardik was in a tizzy.  He was trying to ping me &lt;em&gt;on an hourly basis&lt;/em&gt; for updates about when my piece would be completed.  I was cranking out code in a rapid manner.  And I had done a good bit of "pre-work".  But there was only so much I could do to finish the features that relied on a data model I'd only been given &lt;em&gt;one business day prior&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;By Tuesday night, Andy was pinging me on Slack and telling me that Hardik was gonna throw a whole bunch of other devs into the mix.  Presumably, to implement the features that I hadn't been able to complete.  (Again, these were the features that I could only really finish coding &lt;em&gt;since the previous Friday&lt;/em&gt;.)&lt;/p&gt;

&lt;p&gt;For the next week, I wasted a massive amount of effort.  We had &lt;em&gt;four different devs&lt;/em&gt; coding multiple features that resided in the same handful of code files.  On numerous occasions, I went to submit a PR, only to realize that someone else had already submitted their own version of the feature.  All of us were constantly dealing with merge conflicts.&lt;/p&gt;

&lt;p&gt;Despite all of this anarchy, we got the features implemented and promoted to the LLEs.  That's when I went to Seattle for a team onsite meeting in the third week of October.&lt;/p&gt;

&lt;p&gt;Stay tuned for Part 2...&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Embedding Data Into React/JSX Elements</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Wed, 22 Mar 2023 01:03:10 +0000</pubDate>
      <link>https://dev.to/bytebodger/embedding-data-into-reactjsx-elements-3jcp</link>
      <guid>https://dev.to/bytebodger/embedding-data-into-reactjsx-elements-3jcp</guid>
      <description>&lt;p&gt;What I'm about to show you is really pretty basic.  So Code Gurus out there can feel free to breeze on by this article.  But I've rarely seen this technique used, even in "established" codebases crafted by senior devs.  So I decided to write this up.&lt;/p&gt;

&lt;p&gt;This technique is designed to extract bits of data that have been embedded into a JSX (or... plain ol' HTML) element.  Why would you need to do this?  Well... I'm glad you asked.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5oqpbs5195vl12h69jdr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5oqpbs5195vl12h69jdr.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scenario
&lt;/h2&gt;

&lt;p&gt;Let's look at a really basic function:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This function simply builds a particular row of table cells.  It's used in my &lt;a href="https://paintmap.studio" rel="noopener noreferrer"&gt;https://paintmap.studio&lt;/a&gt; app to build a "color map".  It generates a giant grid (table) that shows me, for every block in the grid, which one of my paints most-closely matches that particular block.&lt;/p&gt;

&lt;p&gt;Once this feature was built, I decided that I wanted to add an &lt;code&gt;onClick&lt;/code&gt; event to each cell.  The idea is that, when you click on any given cell, it then highlights every cell in the grid that contains the same color as the one you've just clicked upon.&lt;/p&gt;

&lt;p&gt;Whenever you click on a cell, the &lt;code&gt;onClick&lt;/code&gt; event handler needs to understand &lt;em&gt;which&lt;/em&gt; color you've chosen.  In other words, you need to &lt;em&gt;pass&lt;/em&gt; the color &lt;em&gt;into&lt;/em&gt; the &lt;code&gt;onClick&lt;/code&gt; event handler.  Over and over again, I see code that looks like this to accomplish that kinda functionality:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleCellClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The code above isn't "wrong".  It will pass the &lt;code&gt;paintIndex&lt;/code&gt; to the event handler.  But it isn't really... &lt;em&gt;optimal&lt;/em&gt;.  The inefficiency that arises is that, for every single table cell, we're creating a brand new function definition.  That's what &lt;code&gt;paintIndex =&amp;gt; handleCellClick(paintIndex)&lt;/code&gt; does.  It spins up an entirely new function.  If you have a large table, that's a lotta function definitions.  And those functions need to be redefined not just on the component's initial render, but &lt;em&gt;whenever this component is re-invoked&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Ideally, you'd have a &lt;em&gt;static&lt;/em&gt; function definition for the event handler.  That would look something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCellClick&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the above code, the &lt;code&gt;handleCellClick&lt;/code&gt; has already been defined outside this function.  So React doesn't need to rebuild a brand new function definition every single time that we render a table cell.  Unfortunately, this doesn't entirely work either.  Because now, every time the user clicks on a table cell, the event handler will have no idea which &lt;em&gt;particular&lt;/em&gt; cell was clicked.  So it won't know which &lt;code&gt;paintIndex&lt;/code&gt; to highlight.&lt;/p&gt;

&lt;p&gt;Again, the way I &lt;em&gt;normally&lt;/em&gt; see this implemented, even in well-built codebases, is to use the &lt;code&gt;paintIndex =&amp;gt; handleCellClick(paintIndex)&lt;/code&gt; approach.  But as I've already pointed out, this is inefficient.  &lt;/p&gt;

&lt;p&gt;So let's look at a couple ways to remedy this.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwtcoy6ls3pb76oq4qp01.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwtcoy6ls3pb76oq4qp01.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapper Components
&lt;/h2&gt;

&lt;p&gt;One approach is to create a wrapper component for my table cells.  That would look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyTableCell&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/MyTableCell&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In this scenario, we're no longer using the base HTML attribute of &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt;.  Instead, there's a custom component, that will accept &lt;code&gt;paintIndex&lt;/code&gt; as a prop, and then presumably use that prop to build the event handler.  &lt;code&gt;MyTableCell&lt;/code&gt; would look something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyTableCell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCellClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// event handler logic using paintIndex&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCellClick&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Using this approach, we don't have to pass the &lt;code&gt;paintIndex&lt;/code&gt; value &lt;em&gt;into the &lt;code&gt;handleCellClick&lt;/code&gt; event handler&lt;/em&gt;, because we can simply reference it from the prop.  There's much to like in this solution because it's consistent with an idiomatic approach to React.  Ideally, you'd even &lt;em&gt;memoize&lt;/em&gt; the &lt;code&gt;MyTableCell&lt;/code&gt; component so it doesn't get remounted (and re &lt;em&gt;rendered&lt;/em&gt;) every time we build a table cell that uses the same paint color.&lt;/p&gt;

&lt;p&gt;However, this approach can also feel a bit onerous because we're cranking out another component purely for the sake of making that one &lt;code&gt;onClick&lt;/code&gt; event more efficient.  Also, if the &lt;code&gt;handleCellClick&lt;/code&gt; event handler needs to do other logic that impacts that state &lt;em&gt;in the calling component&lt;/em&gt;, the resulting code can get a bit "heavy".&lt;/p&gt;

&lt;p&gt;Sometimes you want the logic for that event handler to be handled right inside the calling component.  Luckily, there are other ways to do this.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fkrr0uiuawld3q5jgwl71.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fkrr0uiuawld3q5jgwl71.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML Attributes
&lt;/h2&gt;

&lt;p&gt;HTML affords us a lot of freedom to "stuff" data where it's needed.  For example, you could use the &lt;code&gt;longdesc&lt;/code&gt; attribute to embed the &lt;code&gt;paintIndex&lt;/code&gt; right into the HTML element itself.  Unfortunately, &lt;code&gt;longdesc&lt;/code&gt; is only "allowed" in &lt;code&gt;&amp;lt;frame&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; elements.&lt;/p&gt;

&lt;p&gt;Granted, browsers are tremendously forgiving about the usage of HTML attributes.  So if you were to start putting &lt;code&gt;longdesc&lt;/code&gt; attributes on all sorts of "illegal" HTML elements, it really won't &lt;em&gt;break&lt;/em&gt; anything.  The browser will basically just &lt;em&gt;ignore&lt;/em&gt; the non-idiomatic attributes.  In fact, you can even add your own &lt;em&gt;custom&lt;/em&gt; attributes to HTML elements.  &lt;/p&gt;

&lt;p&gt;Nevertheless, it's usually good practice to avoid stuffing a buncha non-allowed or completely-custom attributes into your HTML elements.  But we have more options.  More "standard" options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Near) Universal HTML Attributes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you wanna find an attribute that you can put on pretty much any element, the first things is to look at the attributes that are allowed in (almost) any elements.  They are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;class&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;style&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;title&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dir&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lang&lt;/code&gt; / &lt;code&gt;xml:lang&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The nice thing about these attributes is that you can pretty much use them anywhere within the &lt;em&gt;body&lt;/em&gt; of your HTML, on pretty much &lt;em&gt;any&lt;/em&gt; HTML element, and you don't have to worry about whether they're "allowed".  You can, for example, put a &lt;code&gt;title&lt;/code&gt; attribute on a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;, or a &lt;code&gt;dir&lt;/code&gt; attribute on a &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt;.  It's all "acceptable" - by HTML standards, that is.&lt;/p&gt;

&lt;p&gt;So if you wanted to use one of these attributes to "pass" data into an event handler, what would be the best choice?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;title&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First of all, as tempting as it may be to use something like &lt;code&gt;title&lt;/code&gt;, I would &lt;em&gt;not&lt;/em&gt; recommend this.  &lt;code&gt;title&lt;/code&gt; is used by screen readers and you're gonna jack up the accessibility of your site if you stuff a bunch of programmatic data into that attribute - data that should &lt;em&gt;not&lt;/em&gt; be read by a screen reader.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;dir&lt;/code&gt;, &lt;code&gt;lang&lt;/code&gt;, &lt;code&gt;xml:lang&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Similarly, you should avoid appropriating the &lt;code&gt;dir&lt;/code&gt;, &lt;code&gt;lang&lt;/code&gt;, or &lt;code&gt;xml:lang&lt;/code&gt; attributes.  Messing with these attributes could jack up the utility of the site for international users (i.e., those who are using your site &lt;em&gt;with a different language&lt;/em&gt;).  So please, leave those alone as well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;style&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Also, you could try to cram "custom" data into a &lt;code&gt;style&lt;/code&gt; attribute.  But IMHO, that's gonna come out looking convoluted.  &lt;em&gt;In theory&lt;/em&gt;, you could define a custom style property like this:&lt;/p&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;td&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Then you could try to read this made-up style property on the element when it's captured in the event handler.  But... I don't recommend such an approach.  Not at all.  First, if you have any &lt;em&gt;legitimate&lt;/em&gt; &lt;code&gt;style&lt;/code&gt; properties set on the element, you're gonna end up with a mishmash of &lt;em&gt;real&lt;/em&gt; and &lt;em&gt;made-up&lt;/em&gt; properties.  Second, there's no reason to embed data in such a verbose format.  You can do it much "cleaner" with the other options at our disposal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;id&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;id&lt;/code&gt; attribute can be a great place to "embed" data.  Here's what that would look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCellClick&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Here, we're using the &lt;code&gt;paintIndex&lt;/code&gt; &lt;em&gt;as the &lt;code&gt;id&lt;/code&gt;&lt;/em&gt;.  Why would we do this?  Because then we can create an event handler that looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCellClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleHighlightedColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This works because the synthetic event that's passed to the event handler will have the &lt;code&gt;id&lt;/code&gt; of the clicked element embedded within it.  This allows us to use a generic event handler on each table cell, while still allowing the event handler to understand exactly &lt;em&gt;which&lt;/em&gt; &lt;code&gt;paintIndex&lt;/code&gt; was clicked upon.&lt;/p&gt;

&lt;p&gt;This can still have some drawbacks.  First of all, &lt;code&gt;id&lt;/code&gt;s are supposed to be &lt;em&gt;unique&lt;/em&gt;.  In the example above, a given &lt;code&gt;paintIndex&lt;/code&gt; may be present in a single table cell - or in hundreds of them.  And if we simply use the &lt;code&gt;paintIndex&lt;/code&gt; value as the &lt;code&gt;id&lt;/code&gt;, we'll end up with many table cells that have identical &lt;code&gt;id&lt;/code&gt; values.  (To be clear, having duplicate &lt;code&gt;id&lt;/code&gt;s won't break your HTML &lt;em&gt;display&lt;/em&gt;.  But in some scenarios it can break your JavaScript &lt;em&gt;logic&lt;/em&gt;.)&lt;/p&gt;

&lt;p&gt;Thankfully, we can fix that, too.  Notice that our table cells have &lt;code&gt;key&lt;/code&gt; values.  And keys &lt;em&gt;must&lt;/em&gt; be unique.  In this scenario, I addressed that problem by using the row/cell counts to build the key.  Because no two cells will have the same combination of row/cell numbers.  We can add the same format to our &lt;code&gt;id&lt;/code&gt;.  That looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCellClick&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now, there will never be a duplicate &lt;code&gt;id&lt;/code&gt; on any of our cells.  But we still have the &lt;code&gt;paintIndex&lt;/code&gt; value embedded &lt;em&gt;into&lt;/em&gt; that &lt;code&gt;id&lt;/code&gt;.  So how do we extract the value in our event handler?  That looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCellClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleHighlightedColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&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;Since we wrote this code, and since we determined the naming convention for the &lt;code&gt;id&lt;/code&gt;, we also know that the &lt;code&gt;paintIndex&lt;/code&gt; value will be the last value in a string of values that are delimited by &lt;code&gt;-&lt;/code&gt;.  If we &lt;code&gt;split('-')&lt;/code&gt; that string and then &lt;code&gt;pop()&lt;/code&gt; the last value off the end of it, we know that we're getting the &lt;code&gt;paintIndex&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;class&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;class&lt;/code&gt; is also a great place to "embed" data - even if it doesn't map to any CSS class that's available to the script.  If you're familiar with jQuery UI, you've probably seen many instances where &lt;code&gt;class&lt;/code&gt; is used as a type of "switch" that doesn't actually drive CSS styles.  Instead, it tells the JavaScript code &lt;em&gt;what to do&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Of course, in JSX we don't use &lt;code&gt;class&lt;/code&gt;.  We use &lt;code&gt;className&lt;/code&gt;.  So that solution would look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCellClick&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And the event handler looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCellClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleHighlightedColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&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;Just as we previously grabbed &lt;code&gt;paintIndex&lt;/code&gt; from the event object's &lt;code&gt;id&lt;/code&gt; field, we're now grabbing it from &lt;code&gt;className&lt;/code&gt;.  How would this work if you also had "real" CSS classes in the &lt;code&gt;className&lt;/code&gt; property?  That would look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCellClick&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And the event handler would look like this:'&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCellClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleHighlightedColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The "cell" class on the &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; is a "real" class - meaning that it maps to predefined CSS properties.  But we also embedded the &lt;code&gt;paintIndex&lt;/code&gt; value into the &lt;code&gt;className&lt;/code&gt; property and we extracted it by splitting the string on empty spaces.&lt;/p&gt;

&lt;p&gt;To be fair, this approach may feel a bit... "brittle".  Because it depends upon the &lt;code&gt;paintIndex&lt;/code&gt; value being the last value in the space-delimited &lt;code&gt;className&lt;/code&gt; string.  If another developer came in and added another CSS class to the end of the &lt;code&gt;className&lt;/code&gt; field, like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; anotherCSSClass`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCellClick&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The logic would &lt;em&gt;break&lt;/em&gt;.  Because the event handler would grab &lt;code&gt;anotherCSSClass&lt;/code&gt; off the end of the string - and try to treat it like it's the &lt;code&gt;paintIndex&lt;/code&gt;.  If you'd like to make it a bit more robust, you can change the logic to something like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell paintIndex-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; anotherCSSClass`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCellClick&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And then update the event handler like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCellClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;className&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paintIndex-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleHighlightedColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&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;By doing it this way, the value that's extracted for &lt;code&gt;paintIndex&lt;/code&gt; isn't dependent upon being the &lt;em&gt;last&lt;/em&gt; item in the space-delimited string.  It can exist anywhere inside the &lt;code&gt;className&lt;/code&gt; property, as long as it's prepended with "paintIndex-".&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fiwc7mjwje7c67omif9pw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fiwc7mjwje7c67omif9pw.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Should You Care?
&lt;/h2&gt;

&lt;p&gt;To be frank, in small apps, having something like this isn't exactly a federal crime:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handleCellClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&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;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The performance "hit" you incur by defining a new function definition inside the &lt;code&gt;onClick&lt;/code&gt; property is... minimal.  In some cases, trying to "fix" it could be understandably defined as a "micro-optimization".   But I do believe it's a solid practice to get in the habit of avoiding these whenever possible.  &lt;/p&gt;

&lt;p&gt;When the event handler doesn't need to have information passed into it from the clicked element, it's a no-brainer to keep arrow functions out of your event properties.  But when it &lt;em&gt;does&lt;/em&gt; require element-specific info, too often I see people blindly fall back on the easy method of dropping arrow functions into their properties.  But there are many ways to avoid this - and they require little additional effort.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Get Your First Job as a Self-Taught Programmer</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Fri, 17 Mar 2023 07:00:54 +0000</pubDate>
      <link>https://dev.to/bytebodger/how-to-get-your-first-job-as-a-self-taught-programmer-1m1c</link>
      <guid>https://dev.to/bytebodger/how-to-get-your-first-job-as-a-self-taught-programmer-1m1c</guid>
      <description>&lt;p&gt;A few years ago, I wrote an article right here on Dev.to called One Crazy Trick to Become a Programmer.  (You can read it here: &lt;a href="https://dev.to/bytebodger/one-crazy-trick-to-become-a-programmer-j8k"&gt;https://dev.to/bytebodger/one-crazy-trick-to-become-a-programmer-j8k&lt;/a&gt;)  Since that time, I've received numerous emails and comments from aspiring coders who are still asking me how to break into the world of professional coding.  So I've finally decided to take this a step further and provide some more-detailed suggestions on how to get started as a professional developer.&lt;/p&gt;

&lt;p&gt;To be absolutely clear, I still stand behind everything I wrote in that original article.  The "soul" of that article is just as applicable today as it was in 2020.  But I'll also admit that the original article was a bit... glib.  It was also very general - pounding away on the simple (but &lt;em&gt;useful&lt;/em&gt;!) mantra of, "WRITE MORE CODE".&lt;/p&gt;

&lt;p&gt;Recently, it's become apparent that some people just aren't sure how to translate the &lt;em&gt;general&lt;/em&gt; bromides in that article into specific, &lt;em&gt;actionable&lt;/em&gt; steps toward fulltime employment.  So I'm gonna take it a step further by trying to provide more-targeted advice.&lt;/p&gt;

&lt;p&gt;I'm also going to target this article specifically toward the &lt;em&gt;self-taught crowd&lt;/em&gt;.  I'm doing this for one simple reason:&lt;/p&gt;

&lt;p&gt;I myself am entirely self-taught.  I've never attended a code camp.  I've never taken a single course (college or otherwise) on coding.  Everything in my modest brain is there because, at some point, I had to sit down, &lt;em&gt;by myself&lt;/em&gt;, and figure out how all this stuff works.  So I guess you could say that I have a bit of a soft spot for other self-taught devs.&lt;/p&gt;

&lt;p&gt;Of course, I realize that there are people with comp-sci degrees who are also struggling to get their first real programming jobs.  And if you're in that crowd, there will still be some actionable nuggets of wisdom for you in this article.  But my target audience is all the people who received no &lt;em&gt;formal&lt;/em&gt; training in application development.&lt;/p&gt;

&lt;p&gt;I'm also gonna write this mostly from the perspective of &lt;em&gt;frontend&lt;/em&gt; development.  But I think the lessons would apply equally if you're a self-taught backend dev.  Just swap out some of the technologies that I mention for those that are more applicable to your scenario.&lt;/p&gt;

&lt;p&gt;So... let's dive in.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fkuhm1ohbt3fw4wh3l4zy.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fkuhm1ohbt3fw4wh3l4zy.jpeg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills vs. Experience
&lt;/h2&gt;

&lt;p&gt;The whole point of my "WRITE MORE CODE" mantra (from the original article) was that no one can magically give you experience.  Experience only comes over time.  But you can give &lt;em&gt;yourself&lt;/em&gt; skills.  And the only way you get more skilled as a programmer is to... write more code.&lt;/p&gt;

&lt;p&gt;But I'm not gonna take all of &lt;em&gt;this&lt;/em&gt; article to just keep hammering away on that mantra.  I'm gonna suggest some things you can do to bolster your skills while you're searching for that first company that will grant you some experience.&lt;/p&gt;

&lt;p&gt;The first thing is to tailor your employer-facing persona to focus on your skills, and &lt;em&gt;not&lt;/em&gt; on your experience.  This means that your resume should be skill-centric.  Your &lt;em&gt;website&lt;/em&gt; should be skill-centric (more on this later...).  Any personal projects you take on should be focused on &lt;em&gt;broadening&lt;/em&gt; your skills.  Basically, you should be constantly thinking about what you can do to add more tools to your toolbelt.&lt;/p&gt;

&lt;p&gt;For example, I see many newbies who've been diving into React.  And that's great!  There's broad demand for React devs and it's wise to have a solid grasp of the library.  But many of these devs can do little else &lt;em&gt;besides&lt;/em&gt; React.&lt;/p&gt;

&lt;p&gt;Have you worked at all with jQuery? (Yes, that technology is getting a little long-in-the-tooth, but it's still massively used and it can teach you a lot about certain core JavaScript concepts - such as anonymous functions.)&lt;/p&gt;

&lt;p&gt;How comfortable are you with JavaScript &lt;em&gt;and&lt;/em&gt; TypeScript?  They're used almost interchangeably today in the workplace and it can be a liability if you're a TypeScript wizard but you get uncomfortable if someone asks you to code something up in plain JavaScript (or vice versa).&lt;/p&gt;

&lt;p&gt;Have you experimented, at all, with other frameworks like Angular? Or Vue?  Or Svelte? &lt;/p&gt;

&lt;p&gt;How about Node?  It is, afterall, JavaScript.  But it's amazing how many freshly-minted, so-called JavaScript devs can seize up at the site of a Node application.&lt;/p&gt;

&lt;p&gt;I fully realize that, as a newbie in the field, it can feel incredibly daunting to have to tackle all these different "angles" of frontend/JavaScript development.  And I'm not asking you to become a JS/TS/React/Angular/jQuery/Node/Vue/Svelte superhero all on your own.  But the more of these &lt;em&gt;skills&lt;/em&gt; that you can confidently boast about on your resume (and hopefully, during interviews), the better off you'll be.&lt;/p&gt;

&lt;p&gt;The point here is that you can't make up a robust job history out of whole cloth.  So you'll need to do everything you can to ensure that you can at least boast a well-rounded skillset.  You're gonna need to find ways to build up a resume without relying on the one thing that shines in most resumes - a robust &lt;em&gt;job&lt;/em&gt; history.  That's why you need to focus so hard on bolstering your list of skills.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fi3w91dvlacfz8yeh0u6j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fi3w91dvlacfz8yeh0u6j.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Do NOT Skimp On HTML/CSS
&lt;/h2&gt;

&lt;p&gt;I could've shoved this under the prior section, but I'm listing it here separately because the modern code camp culture has, IMHO, spawned a small army of new devs who feel pretty good about their JavaScript skills - but have only basic knowledge of HTML/CSS.  It's easy for HTML/CSS to feel almost like an afterthought.  But it should be your &lt;em&gt;first&lt;/em&gt; thought.&lt;/p&gt;

&lt;p&gt;Without HTML/CSS, you have no web app.  And if your answer to every presentation challenge is to throw everything into a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; and slap a few style attributes on it, potential employers are gonna spot this right away.&lt;/p&gt;

&lt;p&gt;How confident are you with Flexbox?  How about Bootstrap?  Do you know what "responsive design" means?  Can you &lt;em&gt;build&lt;/em&gt; a responsive site?  There was a time when some of these challenges could be shunted to the &lt;em&gt;design&lt;/em&gt; team.  But nowadays, employers expect their frontend devs to be completely comfortable with all aspects of HTML/CSS.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F9whvj4kw2tvpjczvazcd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F9whvj4kw2tvpjczvazcd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Have a GitHub Presence
&lt;/h2&gt;

&lt;p&gt;If you don't already have a GitHub account, you need to do so.  Now.&lt;/p&gt;

&lt;p&gt;No... seriously.  If you don't have a GitHub account, &lt;em&gt;stop reading this article and go create one&lt;/em&gt;.  &lt;em&gt;RIGHT.  NOW.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You may be thinking, "I don't have anything to put &lt;em&gt;in&lt;/em&gt; a GitHub account."  I don't care.  The first step is to have a GitHub account.&lt;/p&gt;

&lt;p&gt;Why is this important?  Because you don't have any &lt;em&gt;job&lt;/em&gt; history to speak of.  So the only thing you can do is to start documenting your &lt;em&gt;code&lt;/em&gt; history.  &lt;/p&gt;

&lt;p&gt;Maybe you don't have any repos right now.  But from this day forward, every time you complete a coding challenge or spin up some bare-bones web demo, I want you to create a new repo under your GitHub account and store it there.  The code in those repos may not be the prettiest or the most advanced.  Heck, it may look downright amateurish to a seasoned dev.  But you know what looks even worse?  &lt;em&gt;Having no public code presence to point potential employers to.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To be frank, I delayed opening a GitHub account for many years.  (Although it wasn't a huge problem for me because I was already an established dev before GitHub even existed.)  I used to have &lt;em&gt;dozens&lt;/em&gt; of little test/demo apps on my local machine that I played around with, but I never put them on GitHub.  But those little apps at least provide &lt;em&gt;some&lt;/em&gt; evidence of your skillset and the type of work you can do.&lt;/p&gt;

&lt;p&gt;A GitHub account also has another (seemingly obvious) benefit.  It forces you to get more comfortable with &lt;code&gt;git&lt;/code&gt; (if you're not already).  In modern dev, &lt;code&gt;git&lt;/code&gt; is not a "nice to have".  It's a core skillset.  As a dev manager, a JavaScript savant who struggles with basic &lt;code&gt;git&lt;/code&gt; commands is borderline-useless to me.&lt;/p&gt;

&lt;p&gt;(Side note:  Last year, &lt;em&gt;at Amazon&lt;/em&gt;, there was a guy on our team who somehow managed to get hired without having basic &lt;code&gt;git&lt;/code&gt; skills.  He lasted all of two months.  Quite frankly, I'm surprised he lasted that long.)&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F1j09xh70wp856919nlmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1j09xh70wp856919nlmw.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Open an AWS Account
&lt;/h2&gt;

&lt;p&gt;Now that you have a GitHub presence, take the next step and open an AWS account.  If you're worried about the cost, don't be.  It's free to open an account.  Most of their services are free to use for the first year.  Even after that first year, any costs to you should be extremely minimal unless you start hosting torrents or doing some other kinda high-traffic activity.&lt;/p&gt;

&lt;p&gt;I currently have four sites in AWS.  And my monthly bill is usually about $8.&lt;/p&gt;

&lt;p&gt;Maybe you're thinking that you have no need for AWS because you're not hosting/building public websites/apps.  But I'm telling you, it makes life sooooo much easier when you decide to launch even your first little utility.&lt;/p&gt;

&lt;p&gt;Using AWS Amplify, I can create a new GitHub repo, throw up some bare-bones code, then hook that repo up to Amplify and have it published, on the web, &lt;em&gt;in minutes&lt;/em&gt;.  If you want your own domain name for the app, you can purchase that right in AWS with Route 53 and have it live in less than an hour.  Amplify even provisions an SSL certificate &lt;em&gt;for free&lt;/em&gt; for all of your Amplify sites.&lt;/p&gt;

&lt;p&gt;Once you have a GitHub repo hooked up to an AWS Amplify account, every single time you push new code to the repo, it will automatically build-and-deploy your latest code to the public website.  It's sooooo easy.  And cheap.&lt;/p&gt;

&lt;p&gt;Not only does this give you a quick-and-easy (and cheap) path to launch &lt;em&gt;anything&lt;/em&gt;, but it will also get you acclimated with the AWS ecosystem, which is a huge selling point with many potential employers.  Even if the company you're aiming to work for doesn't use AWS, it looks good on your resume to be able to say that you're familiar with it.&lt;/p&gt;

&lt;p&gt;To be clear, AWS is a massive beast in itself.  And I'm not telling you to become an AWS Ninja.  I'm just suggesting this as one potential way to A) bolster your resume, and B) have a swift path to launch anything that you'd like to publicly display.  Of course, you don't have to use AWS.  There are other cloud-computing solutions that will give you similar capabilities and experience.  The exact platform you choose is up to you.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fm7jl95ify8xcz2hyck3n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fm7jl95ify8xcz2hyck3n.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Stuff
&lt;/h2&gt;

&lt;p&gt;Now that you have a GitHub account to house your code, and you have an AWS account to deploy your code, you need to have some... code.  Yes, this is basically an extension of my "WRITE MORE CODE" mantra.  But again, if you don't have a formal &lt;em&gt;work&lt;/em&gt; history, you're gonna need some way to at least demonstrate your &lt;em&gt;skill&lt;/em&gt; history.&lt;/p&gt;

&lt;p&gt;If you're not sure &lt;em&gt;what&lt;/em&gt; to build, start with your personal portfolio site.  Maybe you haven't done that because you don't &lt;em&gt;have&lt;/em&gt; any kinda meaningful portfolio to speak of.  But even if your site contains nothing but your resume and a few other trivia facts about yourself, it's a good "first step" to getting a public coding presence.&lt;/p&gt;

&lt;p&gt;One important note here:  Do NOT half-ass your personal site.  Spend some time on it.  Try to make it &lt;em&gt;look&lt;/em&gt; nice, even if it's weak on content.  Pay attention to details like performance and accessibility.  (HINT: You can use Lighthouse to generate performance/accessibility reports for your site.)  Just &lt;em&gt;last week&lt;/em&gt;, a hiring manager at a place where I'm interviewing (and I expect to receive an offer in the next coupla days) told me, during our interview, that he pulled up my site and he was amazed at how well it scored.  He said that he frequently does this for candidates and usually the scores are abysmal.&lt;/p&gt;

&lt;p&gt;But don't stop building stuff once you have a personal site up-and-running.  Build &lt;em&gt;more&lt;/em&gt; stuff.  I don't even care &lt;em&gt;what&lt;/em&gt; you build.  The purpose here is not to illustrate that you are The World's Greatest Coder.  The purpose is simply to demonstrate to potential employers that you are, in fact, &lt;em&gt;a coder&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I don't even care if you're launching &lt;em&gt;static&lt;/em&gt; sites.  Put up a site for your church, or your D&amp;amp;D group, or... whatever.  It may not be incredibly fun or engaging.  But you gotta start somewhere.  And you'll learn things - even if the stuff you're building isn't all that challenging.&lt;/p&gt;

&lt;p&gt;Of course, if you can build something that better demonstrates your full coding skillset, then all the better.  You can launch some simple utilities.  You can launch something that leverages/extends a public API.  You can even launch a site that contains tutorials on &lt;em&gt;how to code&lt;/em&gt;.  I don't care what you build.  Just build &lt;em&gt;something&lt;/em&gt;.  And make sure that it's available for you to brag about when talking to potential employers.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fdctmdz7r2xx4hcxb5z8z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fdctmdz7r2xx4hcxb5z8z.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Everything You're Building to Bolster Your Resume
&lt;/h2&gt;

&lt;p&gt;Let's imagine that you've been trying to get a "real" programming job for the last two years.  During that time, you've been working on personal coding projects and developing websites/apps for friends/colleagues.  During the same period, you've &lt;em&gt;also&lt;/em&gt; been working as a waiter to pay the bills.  Many people would represent that on their resume like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

EXPERIENCE:

2021-Present
Waiter @ Joe's Chicken Hut
Responsibilities: Spitting in food; Angering customers; Taking smoke 
breaks;


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

&lt;/div&gt;

&lt;p&gt;In other words, they wouldn't put anything on their resume that pertains to coding because they don't have a "real" coding job.  But here's how this &lt;em&gt;should be&lt;/em&gt; represented on your resume:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

EXPERIENCE:

2021-Present
Self-Employed @ My Awesome Digital Solutions, LLC
Responsibilities: Launched a new website for a local faith-based 
organization; Forked ChatGPT to create an interactive tool for 
interview preparation; Developed a utility for managing Spotify 
playlists; Partnered with local dev users group to craft coding 
tutorials;
Technologies Used: TypeScript, JavaScript, HTML/CSS, Bootstrap, 
jQuery, GitHub, AWS, REST, GraphQL, React, Redux

2021-Present
Waiter @ Joe's Chicken Hut
Responsibilities: Spitting in food; Angering customers; Taking smoke 
breaks;


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

&lt;/div&gt;

&lt;p&gt;If you're thinking, "But I didn't get &lt;em&gt;paid&lt;/em&gt; for those projects," you're missing the entire point.  It doesn't matter if your total income from My Awesome Digital Solutions, LLC over the last two years was $27.83.  As long as you actually &lt;em&gt;did&lt;/em&gt; the projects listed under that resume entry, you're not lying - not at all.  Also, there's absolutely nothing wrong with having concurrent work histories on your resume.  People do it all the time.&lt;/p&gt;

&lt;p&gt;And how does anyone &lt;em&gt;know&lt;/em&gt; that you actually did those projects, with the technologies that you've cited?  Well, because they're &lt;em&gt;in GitHub&lt;/em&gt;, and probably viewable at some public URL.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5upaho6dq0alyt9ky7vh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5upaho6dq0alyt9ky7vh.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contribute To Open Source Projects
&lt;/h2&gt;

&lt;p&gt;I'm gonna open this section by freely admitting that this suggestion is &lt;em&gt;hard&lt;/em&gt;.  Most open source projects are maintained by a core group of dedicated senior devs who know the package inside-and-out.  Not only can some of those communities be incredibly insular, but it can be extremely difficult for someone who's not already deeply ingrained in the package to even know where to begin.  While it's great, in theory, to say that we should all be doing our part to contribute to open source, in practice, it can be daunting to get even a single line of code approved and merged into an open source project if you're not already deeply ensconced in it.&lt;/p&gt;

&lt;p&gt;So why am I telling you to do this?  Especially if you're not deeply experienced yourself?  Two reasons:&lt;/p&gt;

&lt;p&gt;First, diving into established open source projects is one of the only ways that you can see what "production code" looks like before you've ever had a chance to work in an official programming role.  What do I mean by "production code"?&lt;/p&gt;

&lt;p&gt;Well, there's a nasty little secret that most people don't tell you when you're first learning to code:  The "production code" that you typically see in most live codebases usually looks &lt;em&gt;nothing like any of the code that you've yet been exposed to&lt;/em&gt;.  That may sound like a scary fact.  But it's true.&lt;/p&gt;

&lt;p&gt;When you're going through tutorials, everything is "dumbed down" to the simplest possible level.  This is done on purpose because, if I'm trying to demonstrate a single, targeted principle, I don't want the tutorial to be "muddied up" by the myriad bells-and-whistles that you'd often find in a large-scale app.  I only want to illustrate the targeted principle that I'm trying to demo.&lt;/p&gt;

&lt;p&gt;That makes perfect sense when you're trying to teach a single, simple concept.  But it can cause someone's head to spin the first time they're ever exposed to "real" code out-in-the-wild.  &lt;/p&gt;

&lt;p&gt;I've seen this firsthand.  I've witnessed newbies who managed to get hired, and they showed up on the first day thinking that they know what "real" code looks like.  Then they get exposed to the Big Hairy Real Life App that we work on.  And... they're lost.  In fact, I've seen some of these guys quit a job &lt;em&gt;within days&lt;/em&gt; because they felt completely out of their depth.&lt;/p&gt;

&lt;p&gt;Sometimes live apps look insanely complex because they're &lt;em&gt;legacy&lt;/em&gt; apps that've been cobbled together over many years, and by many different devs, to the point where they've become a certified mess.  But even in &lt;em&gt;new&lt;/em&gt; apps, or even in apps that are fastidiously maintained, the code can still be insanely difficult for a newbie to grok.  This is because that new code isn't some simplified tutorial.  It's a real-live app that has a lot of different "hooks" and dependencies embedded within it.&lt;/p&gt;

&lt;p&gt;If you wanna avoid that massive shellshock the first time someone drops you in the middle of a live codebase (or a coding &lt;em&gt;interview&lt;/em&gt;), there are few options.  Because companies aren't just gonna hand over their codebase for you to learn from.&lt;/p&gt;

&lt;p&gt;But there &lt;em&gt;is&lt;/em&gt; one fabulous way to see what "real" code looks like without having to be &lt;em&gt;hired&lt;/em&gt; at some company.  That way is to jump into an open source project.  Open source projects often have just as much complexity as you would expect to find in corporate apps.  And you don't need to be hired anywhere to start acclimating yourself to it.  It's all right there, publicly available, &lt;em&gt;in GitHub&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The second reason that I want you to start wading into the open source waters is that it can be a great boost to your resume.  For example, let's imagine that you manage to get a pull request, with &lt;em&gt;a single line of code&lt;/em&gt;, merged into the React project.  Now, to be perfectly frank, even accomplishing &lt;em&gt;that&lt;/em&gt; would be quite a challenge.  But if you did???  Well, you could say, with perfect honesty, that you are now &lt;em&gt;a contributor to the React project&lt;/em&gt;.  That'd be quite a nice chit on your resume, dontcha think??&lt;/p&gt;

&lt;p&gt;Sure, your "contribution" would consist of &lt;em&gt;a single line of code&lt;/em&gt;.  But who cares?  You could still say with total integrity that you are, in fact, a contributor to the React project.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fjxt77vn3mim2dp4vxix9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjxt77vn3mim2dp4vxix9.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Consider Code-Adjacent Roles
&lt;/h2&gt;

&lt;p&gt;This suggestion may sting a bit.  If you've had your sights set on a &lt;em&gt;programming&lt;/em&gt; role, you probably don't wanna think about getting hired in QA, or as a business analyst, or as a data analyst, or in desktop support, or as a PM.  But sometimes this can be a way for you to get your foot in the door.&lt;/p&gt;

&lt;p&gt;I've been on many dev teams where I never saw a single newbie hired &lt;em&gt;from outside the company&lt;/em&gt;.  This doesn't happen because someone's trying to punish you.  This happens because newbies can be a &lt;em&gt;liability&lt;/em&gt; on the team - draining time from other devs and potentially introducing bad code.&lt;/p&gt;

&lt;p&gt;But I &lt;em&gt;have&lt;/em&gt; seen, on multiple occasions, where someone within the company who's not technically in a &lt;em&gt;coding&lt;/em&gt; role, gets approved to join a dev team once they've shown that A) they're really a great employee in another role, and B) they actually have coding skills.&lt;/p&gt;

&lt;p&gt;Think about it.  If Joe's coming to us "off the street" and his resume clearly shows that he's &lt;em&gt;never&lt;/em&gt; worked as a programmer before, it's actually pretty reasonable to believe that he may not be cut out for this environment and we may need to escort him out in a frighteningly-short period of time.  &lt;/p&gt;

&lt;p&gt;But if Joe already works for our company (in some other role) and we interact with him on a regular basis, we have the freedom to talk with him whenever we want.  We can see if he's doing any coding-like work in his current role.  Even if he's not doing any coding at all, we'll probably be much more comfortable with the &lt;em&gt;risk&lt;/em&gt; because we already know this guy and we can see how he works. &lt;/p&gt;

&lt;p&gt;I'm not just telling you this in theory.  &lt;em&gt;My&lt;/em&gt; first corporate role was as a "Web Content &lt;em&gt;Editor&lt;/em&gt;".  Sure, I was technically working on the website.  But I wasn't (initially) allowed to make any &lt;em&gt;code&lt;/em&gt; changes.  I was just an &lt;em&gt;editor&lt;/em&gt;.  I updated &lt;em&gt;static text&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But at the point that I was hired into this role, I'd already been coding - on my own - for a number of years.  And when problems cropped up on the site that would normally take weeks/months to get IT to fix, I told them, "Well, you know... &lt;em&gt;I&lt;/em&gt; could actually fix this for you if you want?"  It took a little while, but eventually they realized that I actually knew what I was doing.  By the time I left that company, my official title was "Application Developer".&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fvzfs4jgdi611w9fh98x4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fvzfs4jgdi611w9fh98x4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Blog
&lt;/h2&gt;

&lt;p&gt;I realize that this suggestion will not suit everybody. Writing is a proclivity that some just don't care for.  But blogging can be incredibly useful. &lt;/p&gt;

&lt;p&gt;First, it expands your public presence.  The never-been-hired candidate that no one's ever heard of is often less valuable than the one who has a rich history of blogging about tech issues.&lt;/p&gt;

&lt;p&gt;Second, the mere act of blogging often leads to deeper understanding on the issues that you're writing about.  The blog-reading community is your "rubber ducky".  I can tell you that, on numerous occasions, I've sat down to write a Dev.to blog on some software concept that I thought I fully understood - but by the time that I tried to crank out the explanation in a formal article, I realized that there were flaws in my logic.&lt;/p&gt;

&lt;p&gt;Even if the act of &lt;em&gt;explaining&lt;/em&gt; an issue doesn't highlight the flaws in your logic, you can bet that the commenters probably will.  And you know what?  That's a &lt;em&gt;good&lt;/em&gt; thing.  I've learned some great tips by reading the comments that were made on my own blogs!  That expanded knowledge will only help you in your quest for a dev job.&lt;/p&gt;

&lt;p&gt;You may be thinking that it's silly to blog about programming precisely &lt;em&gt;because&lt;/em&gt; you're so new.  But blogs don't even need to consist of you telling the world how it's done.  Blogs can even be fashioned as open &lt;em&gt;questions&lt;/em&gt; for problems that you're struggling with.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fs85l73amf1w449zwccaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fs85l73amf1w449zwccaf.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pitch Your Services
&lt;/h2&gt;

&lt;p&gt;When you're applying to open positions, you're already at a massive disadvantage.  Job postings are typically created by companies who have significant salaries to offer, so they can afford to be picky.  And the mere fact that the job is &lt;em&gt;advertised&lt;/em&gt; means that there will inevitably be a large number of applicants.  And nearly all of those applicants will be more qualified (at least, on paper) than you.&lt;/p&gt;

&lt;p&gt;But not all jobs start with advertised openings.  If you're paying close attention, sometimes you can &lt;em&gt;pitch&lt;/em&gt; someone on the idea of hiring you.  In such a scenario, you're not competing with All The Other Applicants - because &lt;em&gt;there are no other applicants&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;Imagine that you know a small business owner and you can see him struggling with manual processes.  Then imagine you propose that you could build some tools for him that will &lt;em&gt;automate&lt;/em&gt; those processes - assuming that he hires you.&lt;/p&gt;

&lt;p&gt;Is that likely to work?  No.  But it can't hurt to ask.  You never know...&lt;/p&gt;

&lt;p&gt;And to be clear, even if that small business owner actually &lt;em&gt;does&lt;/em&gt; agree to hire you, the pay may be abysmal.  But it's probably still more than you're making in your current job.  And after a year-or-so of proving yourself in that type of role, your resume will look stronger and you can leverage it into a better role with a company that pays more.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fdiurr5sryf2uvnn9srtq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fdiurr5sryf2uvnn9srtq.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't Give Up
&lt;/h2&gt;

&lt;p&gt;In conclusion, I just wanna say that, &lt;em&gt;I get it&lt;/em&gt;.  I really do.  Finding your first programming gig can be really tough.  Especially when you've got that "self-taught" millstone hanging around your neck.  And I know that I haven't written anything here that's a silver-bullet &lt;em&gt;answer&lt;/em&gt;.  Even if you do everything I'm suggesting, it's still gonna be... hard.&lt;/p&gt;

&lt;p&gt;All I can say is: Keep working on your skills, your public "footprint", and your projects.  There &lt;em&gt;are&lt;/em&gt; opportunities out there, even if they're pretty hard to see at times.&lt;/p&gt;

&lt;p&gt;Best of luck!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>career</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Browser Zoom, CSS, Event Handlers, and Accessibility</title>
      <dc:creator>Adam Nathaniel Davis</dc:creator>
      <pubDate>Thu, 16 Mar 2023 09:10:02 +0000</pubDate>
      <link>https://dev.to/bytebodger/browser-zoom-css-event-handlers-and-accessibility-4phn</link>
      <guid>https://dev.to/bytebodger/browser-zoom-css-event-handlers-and-accessibility-4phn</guid>
      <description>&lt;p&gt;A few weeks ago I was working on some features for my color mapping site (&lt;a href="https://paintmap.studio" rel="noopener noreferrer"&gt;https://paintmap.studio&lt;/a&gt;) and I ran into some very odd edge-case bugs.  I found that when I used Chrome's zoom feature (which also exists in any other modern browser), my seemingly-perfect code was &lt;em&gt;breaking&lt;/em&gt;.  Specifically, CSS properties and React/JavaScript event handlers were simply &lt;em&gt;disappearing&lt;/em&gt; when I viewed the app at different zoom levels.&lt;/p&gt;

&lt;p&gt;Here's the exact scenario (along with the associated fix):&lt;/p&gt;

&lt;p&gt;First, the user selects an image, along with a number of different parameters that determine exactly how that image will be transformed.  The result is that you get a pixelated image that matches the colors in that image to a known set of colors from a palette of paints.  The result looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F12gzlm0iprwnuiwzcpga.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F12gzlm0iprwnuiwzcpga.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In theory, the app will process images of any size.  They &lt;em&gt;could&lt;/em&gt; be small images that are easily viewed onscreen.  But in practice, nearly all the images that I put through the app are fairly large.  Most commonly, they're 1440x1440 pixels.  &lt;/p&gt;

&lt;p&gt;This means that it can be difficult to view the generated image in its entirety.  So when I'm using the app, I usually have my browser's zoom function set to 75%.  On my 4k monitors, this allows me to view the entire 1440x1440 image onscreen without having to scroll horizontally or vertically.&lt;/p&gt;

&lt;p&gt;Another feature of the app is that it will then convert the transformed image into a huge "color map".  This is a massive HTML table where every cell in the table corresponds to one of the pixelated blocks from the transformed image.  But on the map feature, each of those cells contains a number, and each number corresponds to a given color of paint.&lt;/p&gt;

&lt;p&gt;(In case your wondering, the whole purpose of this feature is that I can then copy-n-paste the entire HTML table into a spreadsheet. Once it's in a spreadsheet, I can then use it as a "paint by numbers"-style template.)&lt;/p&gt;

&lt;p&gt;Unfortunately, converting the image into the massive HTML table makes the onscreen output even &lt;em&gt;larger&lt;/em&gt;.  This is necessary because if I try to adhere to the size of the original image, you'll never be able to see all of the numbers in every individual cell.&lt;/p&gt;

&lt;p&gt;So even with my browser set at a 75% zoom, the resulting display looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F9udnhdy6cd0oiuvhpg29.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F9udnhdy6cd0oiuvhpg29.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That may seem somewhat unwieldy because I still have to scroll horizontally and vertically to see the whole image.  But this isn't much of a concern because it's all just gonna get copied-n-pasted into a spreadsheet anyway.  Besides, when you're viewing an image in this format that has 144x144 table cells, there's only so much you can do to make it "presentable" on a single screen.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fzy07yckogp94g2jpv4wm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fzy07yckogp94g2jpv4wm.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding clickable elements
&lt;/h2&gt;

&lt;p&gt;Here's the feature that I needed to add.  When I was looking at the big "color map", I found myself wondering: "How many &lt;em&gt;other&lt;/em&gt; places on the map use the same color as the one that's in &lt;em&gt;this&lt;/em&gt; particular cell?"&lt;/p&gt;

&lt;p&gt;For example, when looking at the following section of the map:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ffsery7m63477fzcs8qb0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffsery7m63477fzcs8qb0.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can see that there are certain blocks that use color #920.  But I wanted to be able to quickly see, at-a-glance, where color #920 occurs &lt;em&gt;in the entire color map&lt;/em&gt;.  So I added some new logic to the code that renders the table cells.  That looked like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getTableCells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;rowIndex&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;anArrayOfInstances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rgbModel&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;anInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;negative&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;highlightedColor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paintIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;darkness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;red&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;green&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blue&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;color&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;backgroundColor&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;highlightedColor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#39ff14&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`rgb(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;red&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;green&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;darkness&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;td&lt;/span&gt;
            &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cell&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`cell-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cellIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleCellClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
               &lt;span class="nx"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="na"&gt;borderWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;highlightedColor&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;paintIndex&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/td&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Here's what's happening in that function:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We grab the &lt;code&gt;highlightedColor&lt;/code&gt; from &lt;code&gt;uiState&lt;/code&gt;.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then for each cell, if that cell represents the &lt;code&gt;highlightedColor&lt;/code&gt;, we set the style to have a neon green background, with a red number, and a border width of 5.  If it's &lt;em&gt;not&lt;/em&gt; the &lt;code&gt;highlightedColor&lt;/code&gt;, then we match the background color of the cell to the "normal" color, with a black number, and a border width of 0.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We set an &lt;code&gt;onClick&lt;/code&gt; handler for each cell that will update the &lt;code&gt;highlightedColor&lt;/code&gt;.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We also set the &lt;code&gt;className&lt;/code&gt; for each cell to &lt;code&gt;cell&lt;/code&gt;.&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;cell&lt;/code&gt; CSS class looked like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.cell&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transform-origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;vertical-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;middle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&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;Notice that I've set the &lt;code&gt;cursor&lt;/code&gt; attribute to &lt;code&gt;pointer&lt;/code&gt; to give an extra visual cue that each individual table cell is indeed &lt;em&gt;clickable&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And the &lt;code&gt;handleCellClick()&lt;/code&gt; event handler looked like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleCellClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;allow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;anObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nx"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleHighlightedColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The end result is that, if I clicked on any cell that contained #920, the previous subsection would look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fczqcgyi84fmw3us9eiri.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fczqcgyi84fmw3us9eiri.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if I zoomed way out, I'd get something that looked like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fy42tyg8z12pppxnffl0q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fy42tyg8z12pppxnffl0q.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This allowed me to quickly see all the other places in the image that used the same color.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F94pthq6i2rdw068evi7q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F94pthq6i2rdw068evi7q.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The zoom problem
&lt;/h2&gt;

&lt;p&gt;At first, I was quite pleased with my new color-highlighting feature.  But then I noticed something really wonky.&lt;/p&gt;

&lt;p&gt;When I viewed the color map with no browser zoom applied, everything worked great.  But viewing it with no zoom meant that I could only see a tiny portion on the screen.  When I went back to my "normal" setting - browser zoom = 75% - something really strange happened.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Most&lt;/em&gt; of the &lt;code&gt;onClick&lt;/code&gt; handlers worked just fine.  But in &lt;em&gt;some portions of the map&lt;/em&gt;, they did &lt;strong&gt;nothing at all&lt;/strong&gt;.  Also, for &lt;em&gt;most&lt;/em&gt; of the table cells, the &lt;code&gt;cursor: pointer&lt;/code&gt; CSS attribute was applied.  But on all of the cells where the &lt;code&gt;onClick&lt;/code&gt; handler was failing, the cursor also reverted to its default value of &lt;code&gt;pointer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I couldn't find any rhyme-or-reason as to why the event/CSS values failed on &lt;em&gt;some&lt;/em&gt; cells, but worked perfectly fine on others.  Furthermore, the exact cells that failed-or-worked varied &lt;em&gt;depending upon the particular zoom setting that I'd chosen in the browser&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;At 75% zoom, a given region of cells would lose their event/CSS settings.  But at 66% zoom, entirely &lt;em&gt;different&lt;/em&gt; regions would lose the settings.  However, I also noticed that, &lt;em&gt;at 50% zoom&lt;/em&gt;, everything worked just fine.  &lt;strong&gt;This was a critical clue as to what was happening.&lt;/strong&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F080obsie3fl5zljmujie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F080obsie3fl5zljmujie.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The dangers of subpixel rendering
&lt;/h2&gt;

&lt;p&gt;You may have noticed that, in most modern IDEs, if you try to manually set a CSS property to a subpixel value (e.g., &lt;code&gt;height: 50.33px&lt;/code&gt;), you'll get some kinda warning.  They do this because browsers can get kinda wonky when you set pixel values that are not integers.&lt;/p&gt;

&lt;p&gt;Of course in my example, I wasn't &lt;em&gt;manually&lt;/em&gt; setting any style attributes to subpixel values.  Everything was set to nice, clean, whole numbers.  But here's the "gotcha":&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When the user manually alters the display with their browser's zoom feature, it forces everything onscreen to be re-rendered.  And those re-renderings will often turn your nice, clean, whole numbers into &lt;em&gt;subpixel calculations&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;For example, I was setting every table cell to have &lt;code&gt;height: 50px&lt;/code&gt; and &lt;code&gt;width: 50px&lt;/code&gt;.  Nothing wrong with that.  But if the user sets the zoom factor to 66%, now every cell height and width becomes &lt;code&gt;33.33px&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now I'm gonna be honest here.  I don't fully understand what happens inside the guts of the browser itself that makes a table cell with &lt;code&gt;height: 33.33px&lt;/code&gt; and &lt;code&gt;width: 33.33px&lt;/code&gt; suddenly &lt;em&gt;lose&lt;/em&gt; it's CSS properties or its event handlers.  But I was able to prove out through experimentation that those subpixel calculations were indeed the source of my problem.&lt;/p&gt;

&lt;p&gt;This explains why, at different zoom levels, &lt;em&gt;some&lt;/em&gt; regions of the color map performed just fine, while &lt;em&gt;other&lt;/em&gt; regions failed.  Because when you're tiling successive table cells on the screen at, say, 66% zoom, the &lt;em&gt;first&lt;/em&gt; cell will be "off" from the screen's normal pixel grid (because of that pesky &lt;code&gt;.33px&lt;/code&gt; modifier).  And the &lt;em&gt;second&lt;/em&gt; cell will also be "off" from the pixel grid (because now that one is essentially shunted by &lt;code&gt;.66px&lt;/code&gt;).  But the &lt;em&gt;third&lt;/em&gt; cell will be able to "snap into" the screen's normal pixel grid.  Because by the time that the third cell is rendered, it's "offset" is &lt;code&gt;1/3 + 1/3 + 1/3 = 1&lt;/code&gt; - meaning that it can snap into the monitor's "normal" display.&lt;/p&gt;

&lt;p&gt;This also explains why my code worked perfectly at 100% zoom, &lt;em&gt;and 50% zoom&lt;/em&gt;, but failed at zoom levels like 66% or 75%.  Because, at 50% zoom, all of my &lt;code&gt;height: 50px; width: 50px;&lt;/code&gt; cells became... &lt;code&gt;height: 25px; width: 25px;&lt;/code&gt; cells - meaning that at 50% zoom, everything was still rendered with nice, clean, whole-number pixel dimensions.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fjt0txsl3226vmn664jp9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjt0txsl3226vmn664jp9.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;Luckily, once I realized what was going on and I did a bit of CSS googling, I was able to solve the whole problem with a &lt;em&gt;single&lt;/em&gt; line of CSS.  I altered my &lt;code&gt;cell&lt;/code&gt; CSS class by adding this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;scaleX&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;scaleY&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This basically tells each cell to scale up to consume 100% of its boundaries.  This in turn seems to clear the problem that the CSS-and-event-handlers had with subpixel-styled elements.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F83l5pf5lena6d4piflpw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F83l5pf5lena6d4piflpw.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  But... who cares??
&lt;/h2&gt;

&lt;p&gt;It's reasonable to look at this odd bug and wonder if you should even care about it at all.  At first, I just filed it away as a weird edge case that I never ran into before - and I'd probably never need to worry about it again.  &lt;/p&gt;

&lt;p&gt;But... I'm actually pretty sure that I &lt;em&gt;have&lt;/em&gt; run into this issue before.  There have been times in the past when I was working on a site and I got tired of scrolling around to verify functionality.  So I'd shrink the screen down so I could see it all in one shot.  But then, after days, or even weeks, of using the site in this manner, I'd find some odd glitch in the app.  &lt;/p&gt;

&lt;p&gt;After investigating it further, and after realizing that none of my colleagues could reproduce the error, I'd realize that the issue only happened &lt;em&gt;for me&lt;/em&gt; because I was the only one using the site on a non-100% zoom level.  So what did I do?  I just flipped my zoom back to 100% and went about my business.  &lt;/p&gt;

&lt;p&gt;Afterall, no one &lt;em&gt;else&lt;/em&gt; had reported the error or was complaining about it in any way.  So I didn't want to burn dev cycles troubleshooting a problem that no one else cared about.&lt;/p&gt;

&lt;p&gt;The only reason that I felt a need to &lt;em&gt;fix&lt;/em&gt; the bug, in this particular case, was because it was important &lt;em&gt;to me&lt;/em&gt;.  Specifically, it "mattered" because it's hard to view those large color maps onscreen unless I'm shrinking it down to a workable size.&lt;/p&gt;

&lt;p&gt;Additionally, even if someone &lt;em&gt;had&lt;/em&gt; complained in the past about features being broken in non-100%-zoomed formats, I'm pretty sure that I would've been fairly dismissive about it.  It's not that I don't care about the user experience.  But my reasoning would have been as such:&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We spend a lot of time painstakingly ensuring that the site works optimally &lt;em&gt;in its default resolution&lt;/em&gt;.  If you feel compelled to change that resolution (for some odd reason), I can't be bothered to test-and-troubleshoot every far-edge-case that results from people using the site &lt;em&gt;in unintended ways&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;Maybe that sounds flippant.  But there are many things you can do/use in a browser that subvert the devs' original intent.  And we can hardly be expected to devote loads of troubleshooting time to your aberrant way of using the app.&lt;/p&gt;

&lt;p&gt;For example:  I've received "bug" tickets from users who said that something was broken on the site.  When I investigated it further, I couldn't recreate the error.  Nor could anyone else on our team.  When I contacted the user directly, I realized that the "bug" was caused because they're using some &lt;em&gt;third-party browser plugin&lt;/em&gt;.  And it's interfering with the site's normal functionality.&lt;/p&gt;

&lt;p&gt;In such scenarios, my answer has always been the same:  Stop using that third-party browser plugin on our site.  Sure, some people have whined about this response.  But I've always received support in this stance from my management chain.  Because trying to ensure that your app works properly &lt;em&gt;no matter which third-party plugin someone chooses to use&lt;/em&gt; is a horrific rabbit hole that yields almost no discernible value.&lt;/p&gt;

&lt;p&gt;Finally, issues caused by browser zoom functionality feel like &lt;em&gt;extreme&lt;/em&gt; edge cases.  I mean, 99.99% of the time when I'm viewing/using &lt;em&gt;any&lt;/em&gt; website, I'm viewing/using it at the default 100% zoom level.  For the vast majority of users out there, they probably use most/all sites at the same 100% zoom level as well.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fj2h8gkldbgu5xvdjc85w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fj2h8gkldbgu5xvdjc85w.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  An accessibility issue
&lt;/h2&gt;

&lt;p&gt;But the more I thought about this, I began to realize this is &lt;em&gt;an accessibility issue&lt;/em&gt;.  And it's one that I don't think many dev teams are really thinking much about.&lt;/p&gt;

&lt;p&gt;I've worked on apps where accessibility was no one's real concern.  We had a limited userbase and management put no priority on accessibility standards.  So we happily cranked out code without worrying about things like A11Y compliance.&lt;/p&gt;

&lt;p&gt;I've also worked on teams where accessibility was a critical concern.  In those shops, we constantly ran auditing tools and preached the importance of accessibility standards in everything we built.&lt;/p&gt;

&lt;p&gt;But even in those "woke" environments, I don't &lt;em&gt;ever&lt;/em&gt; remember &lt;em&gt;anyone&lt;/em&gt; saying that we needed to validate the site's features &lt;em&gt;at different zoom levels&lt;/em&gt;.  But what subset of your userbase is most likely to be using your site/app at varying zoom levels?  That's right.  People with impaired vision.  And if key features of your site simply &lt;em&gt;break&lt;/em&gt; at, say, 125% zoom, you could be alienating those users.&lt;/p&gt;

&lt;p&gt;To be clear, I'm not even sure exactly how you test for this.  Like, if you're writing Jest unit tests, you won't be able to validate functionality at different zoom levels.  You'd need to leverage a headless browser solution.  And I'm not sure if quick auditing tools (like Axe) even check for these things?  I'll have to research that some more.&lt;/p&gt;

&lt;p&gt;At any rate, I'm not trying to upend your current accessibility practices.  And to be fair, maybe in &lt;em&gt;your&lt;/em&gt; dev shop, this is already something that's on your radar.  But I'm just highlighting it as one potential issue that you may need to keep in mind going forward.&lt;/p&gt;

&lt;p&gt;Cheers!  And happy coding.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>css</category>
      <category>a11y</category>
    </item>
  </channel>
</rss>
