<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[What is Web Dev — Learn All About Web Development]]></title><description><![CDATA[A website where you can learn all about web development.]]></description><link>https://whatisweb.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1664986523651/ohYH1iRtT.png</url><title>What is Web Dev — Learn All About Web Development</title><link>https://whatisweb.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 21 Apr 2026 00:13:20 GMT</lastBuildDate><atom:link href="https://whatisweb.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building a Responsive Carousel Component in React: The Complete Guide]]></title><description><![CDATA[In web design, a carousel component is used to display multiple images or pieces of content in a rotating or sliding manner. The carousel component is typically used to highlight featured products, showcase portfolios, present testimonials, or displa...]]></description><link>https://whatisweb.dev/building-a-responsive-carousel-component-in-react-the-complete-guide</link><guid isPermaLink="true">https://whatisweb.dev/building-a-responsive-carousel-component-in-react-the-complete-guide</guid><category><![CDATA[React]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[CSS]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Fri, 23 May 2025 15:30:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747154249853/daa3d57e-a3e5-4032-a57e-d900e6a35985.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In web design, a carousel component is used to display multiple images or pieces of content in a rotating or sliding manner. The carousel component is typically used to highlight featured products, showcase portfolios, present testimonials, or display news articles or blog posts.</p>
<p>While there are awesome libraries and components like Swiper that are used to create responsive and accessible carousels, it's still important to know how to create these components from scratch.</p>
<p>Creating these components from scratch will make you a better React developer and help you appreciate the work that goes into creating these libraries and components.</p>
<p>So without further ado, let’s get started. :)</p>
<h2 id="heading-getting-started">Getting Started</h2>
<p>Before starting, you must have <code>npm</code> installed on your computer, which comes bundled with <a target="_blank" href="https://nodejs.org/en/"><strong>Node.js</strong></a> which you can install from <a target="_blank" href="https://nodejs.org/en/download/"><strong>here</strong></a>.</p>
<h3 id="heading-project-setup">Project Setup</h3>
<p>Run the following commands to initialize the React application and install the required dependencies.</p>
<pre><code class="lang-yaml"><span class="hljs-string">npm</span> <span class="hljs-string">create</span> <span class="hljs-string">vite@latest</span> <span class="hljs-string">react-carousel</span> <span class="hljs-string">--template</span> <span class="hljs-string">react</span>
<span class="hljs-string">cd</span> <span class="hljs-string">react-carousel</span>
<span class="hljs-string">npm</span> <span class="hljs-string">install</span>
<span class="hljs-string">npm</span> <span class="hljs-string">run</span> <span class="hljs-string">dev</span>
</code></pre>
<h3 id="heading-folder-structure">Folder Structure</h3>
<p>Before we start writing any code, let's create the folder structure required for the front-end application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747149341549/3676f901-526f-4f8a-9a4f-7ad7f0542788.png" alt class="image--center mx-auto" /></p>
<p>You can create the above directories with these commands.</p>
<pre><code class="lang-yaml"><span class="hljs-string">cd</span> <span class="hljs-string">react-carousel/src</span>
<span class="hljs-string">mkdir</span> <span class="hljs-string">components</span> <span class="hljs-string">hooks</span>
</code></pre>
<p><strong>(Optional) Adding fonts and styles</strong></p>
<ul>
<li>Add these fonts to the <code>head</code> section of the <code>index.html</code> file under the project’s root directory.</li>
</ul>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&amp;display=swap"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"</span> /&gt;</span>
</code></pre>
<ul>
<li>Replace the <code>CSS</code> inside the <code>index.css</code> with the code below:</li>
</ul>
<pre><code class="lang-css">*<span class="hljs-selector-pseudo">::before</span>,
*,
*<span class="hljs-selector-pseudo">::after</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">box-sizing</span>: border-box;
}

<span class="hljs-selector-class">.material-symbols-outlined</span> {
  <span class="hljs-attribute">font-variation-settings</span>: <span class="hljs-string">"FILL"</span> <span class="hljs-number">0</span>, <span class="hljs-string">"wght"</span> <span class="hljs-number">600</span>, <span class="hljs-string">"GRAD"</span> <span class="hljs-number">0</span>, <span class="hljs-string">"opsz"</span> <span class="hljs-number">48</span>;
}

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Poppins"</span>, sans-serif;
  <span class="hljs-attribute">-webkit-font-smoothing</span>: antialiased;
  <span class="hljs-attribute">-moz-osx-font-smoothing</span>: grayscale;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#9EC6F3</span>;
}
</code></pre>
<h2 id="heading-basic-carousel-layout">Basic Carousel Layout</h2>
<p>Now that we have created the initial set-up required to build and run the application, let’s start by creating the basic carousel layout — that is, the barebones HTML structure of the carousel component.</p>
<p><strong>Note:—</strong> We will use CSS modules to style our React application. So for each component, we will also create a CSS or SCSS file for that component.</p>
<p>Create the <code>Slider.jsx</code> and <code>Slider.module.css</code> files inside the <code>components/Slider</code> folder and add the following code to them.</p>
<p><strong>Slider.jsx</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">//Slider.jsx</span>

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

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Slider.module.css"</span>;

<span class="hljs-keyword">const</span> Slider = <span class="hljs-function">(<span class="hljs-params">{
  items,
  children,
}</span>) =&gt;</span> {

  <span class="hljs-keyword">const</span> sliderItems = items || Children.toArray(children);

  <span class="hljs-keyword">const</span> sliderButtonHandler = <span class="hljs-function">(<span class="hljs-params">direction</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"forward"</span>) {
      <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Add logic to slide to next item</span>
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"backward"</span>) {
      <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Add logic to slide to previous item</span>
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slider}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slidesContainer}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> "<span class="hljs-attr">flex</span>" }}&gt;</span>
          {sliderItems.map((item, index) =&gt; {
            return (
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>
                {item}
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            );
          })}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonPrev</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("backward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">letterSpacing:</span> "<span class="hljs-attr">4px</span>" }}
        &gt;</span>
          arrow_back_ios_new
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonNext</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("forward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}&gt;</span>
          arrow_forward_ios
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Slider;
</code></pre>
<p><strong>Slider.module.css</strong></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.slider</span> {
    <span class="hljs-attribute">position</span>: relative;
    <span class="hljs-attribute">max-width</span>: <span class="hljs-number">1300px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.slidesContainer</span> {
    <span class="hljs-attribute">overflow</span>: hidden;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">8px</span>;
}

<span class="hljs-selector-class">.slideButton</span> {
    <span class="hljs-attribute">position</span>: absolute;
    <span class="hljs-attribute">top</span>: <span class="hljs-number">50%</span>;
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translateY</span>(-<span class="hljs-number">50%</span>);
    <span class="hljs-attribute">height</span>: <span class="hljs-number">48px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">48px</span>;
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">50%</span>;
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> / <span class="hljs-number">15%</span>) <span class="hljs-number">0px</span> <span class="hljs-number">4px</span> <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">border</span>: none;
    <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-class">.slideButton</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-built_in">rgb</span>(<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> / <span class="hljs-number">25%</span>) <span class="hljs-number">0px</span> <span class="hljs-number">4px</span> <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.slideButtonPrev</span> {
    <span class="hljs-attribute">left</span>: -<span class="hljs-number">24px</span>;
}

<span class="hljs-selector-class">.slideButtonNext</span> {
    <span class="hljs-attribute">right</span>: -<span class="hljs-number">24px</span>;
}

<span class="hljs-selector-class">.slideButtonIcon</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#353840</span>;
    <span class="hljs-attribute">font-variation-settings</span>: <span class="hljs-string">"FILL"</span> <span class="hljs-number">0</span>, <span class="hljs-string">"wght"</span> <span class="hljs-number">700</span>, <span class="hljs-string">"GRAD"</span> <span class="hljs-number">0</span>, <span class="hljs-string">"opsz"</span> <span class="hljs-number">48</span>;
}

<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">768px</span>) {
    <span class="hljs-selector-class">.slideButtonPrev</span> {
        <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
    }

    <span class="hljs-selector-class">.slideButtonNext</span> {
        <span class="hljs-attribute">right</span>: <span class="hljs-number">0</span>;
    } 
}
</code></pre>
<p>Modify the <code>App.jsx</code> file to include the newly created <code>Slider</code> component.</p>
<p><strong>App.jsx</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Slider <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Slider/Slider'</span>;

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

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> sliderItems = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>, <span class="hljs-number">11</span>, <span class="hljs-number">12</span>];

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Slider</span>&gt;</span>
            {sliderItems.map((item, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"item"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>{item}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Slider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><strong>App.css</strong></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.item</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">310px</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFF1D5</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#604652</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">102px</span>;
}
</code></pre>
<p>If you open the application in your browser, you’ll notice that the component we created doesn’t look anything like a carousel yet. But bear with me for a moment—we’ll soon add the necessary styles and functionality to turn it into a fully working carousel.</p>
<p>Before we dive into that, let me briefly explain the code we’ve written so far.</p>
<p>The <code>Slider</code> component accepts two props — <code>items</code> and <code>children</code> — either of which can be used to render the carousel content. We’ve also added two navigation buttons to move the slider forward and backward. Finally, we applied basic CSS styling to the component.</p>
<p>In the <code>App</code> component, we pass data to the <code>Slider</code> component by mapping over the <code>sliderItems</code> array.</p>
<h2 id="heading-carousel-logic">Carousel Logic</h2>
<p>Now that we have the layout of the carousel ready, let’s add the functionality needed to turn it into a working carousel.</p>
<p>Update the code inside the <code>Slider.jsx</code> and <code>App.jsx</code> with the code below.</p>
<p><strong>Slider.jsx</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Children, useState, useRef, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Slider.module.css"</span>;

<span class="hljs-keyword">const</span> Slider = <span class="hljs-function">(<span class="hljs-params">{
  slidesPerView: initialSliderPerView = <span class="hljs-number">4</span>,
  spaceBetween: initialSpaceBetween = <span class="hljs-number">16</span>,
  slidesPerGroup: initialSliderPerGroup = <span class="hljs-number">4</span>,  
  items,
  children,
}</span>) =&gt;</span> {
  <span class="hljs-comment">// New Code</span>
  <span class="hljs-keyword">const</span> [slidesPerView, setSlidesPerView] = useState(initialSliderPerView);
  <span class="hljs-keyword">const</span> [slidesPerGroup, setSlidesPerGroup] = useState(initialSliderPerGroup);
  <span class="hljs-keyword">const</span> [spaceBetween, setSpaceBetween] = useState(initialSpaceBetween);

  <span class="hljs-keyword">const</span> [sliderItemWidth, setSliderItemWidth] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> sliderContainerRef = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-comment">// New Code</span>

  <span class="hljs-keyword">const</span> sliderItems = items || Children.toArray(children);

  <span class="hljs-comment">// New Code</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (sliderContainerRef.current) {
      <span class="hljs-keyword">const</span> sliderContainerWidth = sliderContainerRef.current.offsetWidth;

      <span class="hljs-keyword">const</span> elements = sliderContainerRef.current.querySelectorAll(<span class="hljs-string">'.slider-item'</span>);

      elements.forEach(<span class="hljs-function"><span class="hljs-params">el</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> sliderItemWidth = <span class="hljs-built_in">Math</span>.ceil((sliderContainerWidth / slidesPerView) - spaceBetween);

        el.style.width = sliderItemWidth + <span class="hljs-string">'px'</span>;

        <span class="hljs-built_in">Array</span>.from(el.children).forEach(<span class="hljs-function"><span class="hljs-params">div</span> =&gt;</span> {
          div.style.width = sliderItemWidth + <span class="hljs-string">'px'</span>;
        });

        setSliderItemWidth(sliderItemWidth);
      });
    }

  }, [slidesPerView, spaceBetween]);
  <span class="hljs-comment">// New Code</span>

  <span class="hljs-keyword">const</span> sliderButtonHandler = <span class="hljs-function">(<span class="hljs-params">direction</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"forward"</span>) {
      <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Add logic to slide to next item</span>
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"backward"</span>) {
      <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> Add logic to slide to previous item</span>
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slider}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slidesContainer}</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{sliderContainerRef}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> "<span class="hljs-attr">flex</span>" }}&gt;</span>
          {sliderItems.map((item, index) =&gt; {
            return (
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> 
                <span class="hljs-attr">className</span>=<span class="hljs-string">"slider-item"</span> 
                <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>
                <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
                  <span class="hljs-attr">marginRight:</span> <span class="hljs-attr">Number</span>(<span class="hljs-attr">spaceBetween</span>)
                    ? `${<span class="hljs-attr">spaceBetween</span>}<span class="hljs-attr">px</span>`
                    <span class="hljs-attr">:</span> "<span class="hljs-attr">0px</span>",
                }}
              &gt;</span>
                {item}
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            );
          })}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonPrev</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("backward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">letterSpacing:</span> "<span class="hljs-attr">4px</span>" }}
        &gt;</span>
          arrow_back_ios_new
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonNext</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("forward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}&gt;</span>
          arrow_forward_ios
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Slider;
</code></pre>
<p><strong>App.jsx</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Slider <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Slider/Slider'</span>;

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

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> sliderItems = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>, <span class="hljs-number">11</span>, <span class="hljs-number">12</span>];

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex-container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Slider</span>
            <span class="hljs-attr">slidesPerView</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">slidesPerGroup</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">spaceBetween</span>=<span class="hljs-string">{16}</span>
          &gt;</span>
            {sliderItems.map((item, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"item"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>{item}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Slider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><strong>App.css</strong></p>
<pre><code class="lang-css"><span class="hljs-selector-class">.flex-container</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
}

<span class="hljs-selector-class">.item</span> {
  <span class="hljs-attribute">height</span>: <span class="hljs-number">310px</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#FFF1D5</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#604652</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">102px</span>;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747575467813/bef320ab-0323-466e-949f-62f502c63ac5.png" alt="React Carousel" class="image--center mx-auto" /></p>
<p>If you open the application in your browser, you’ll see that the component is starting to look like a carousel, but it doesn’t function like one yet.</p>
<p>Before we make it fully interactive, let’s quickly review the code we’ve written so far.</p>
<p>The <code>Slider</code> component now accepts three additional props: <code>slidesPerView</code>, <code>slidesPerGroup</code>, and <code>spaceBetween</code>.</p>
<ul>
<li><p><code>slidesPerView</code> controls how many items are visible in the viewport at once.</p>
</li>
<li><p><code>slidesPerGroup</code> defines how many items move with each navigation.</p>
</li>
<li><p><code>spaceBetween</code> sets the spacing between each slide.</p>
</li>
</ul>
<p>The component also uses a <code>sliderItemWidth</code> state variable to store the calculated width of each slide. This value is computed using the <code>useEffect</code> hook and a <code>sliderContainerRef</code>, which allow us to dynamically measure the container's width and divide it based on the number of slides per view.</p>
<h3 id="heading-making-it-functional">Making it Functional</h3>
<p>Let’s finally add the logic to turn it into a fully working carousel.</p>
<p>Update the <code>Slider.jsx</code> with the following code:</p>
<p><strong>Slider.jsx</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Slider.jsx</span>
<span class="hljs-keyword">import</span> { Children, useState, useRef, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> useInView <span class="hljs-keyword">from</span> <span class="hljs-string">"../../hooks/useInView"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Slider.module.css"</span>;

<span class="hljs-keyword">const</span> Slider = <span class="hljs-function">(<span class="hljs-params">{
  slidesPerView: initialSliderPerView = <span class="hljs-number">4</span>,
  spaceBetween: initialSpaceBetween = <span class="hljs-number">16</span>,
  slidesPerGroup: initialSliderPerGroup = <span class="hljs-number">4</span>,  
  items,
  children,
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [slidesPerView, setSlidesPerView] = useState(initialSliderPerView);
  <span class="hljs-keyword">const</span> [slidesPerGroup, setSlidesPerGroup] = useState(initialSliderPerGroup);
  <span class="hljs-keyword">const</span> [spaceBetween, setSpaceBetween] = useState(initialSpaceBetween);

  <span class="hljs-comment">// New Code</span>
  <span class="hljs-keyword">const</span> [activeSlideIndex, setActiveSlideIndex] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-comment">// New Code</span>

  <span class="hljs-keyword">const</span> [sliderItemWidth, setSliderItemWidth] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> sliderContainerRef = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-comment">// New Code</span>
  <span class="hljs-keyword">const</span> { <span class="hljs-attr">inView</span>: lastSliderItemInView, <span class="hljs-attr">ref</span>: lastSliderItemRef } = useInView({
    <span class="hljs-attr">root</span>: sliderContainerRef.current,
    <span class="hljs-attr">threshold</span>: <span class="hljs-number">0.95</span>,
  });

  <span class="hljs-keyword">const</span> { <span class="hljs-attr">inView</span>: firstSliderItemInView, <span class="hljs-attr">ref</span>: firstSliderItemRef } = useInView({
    <span class="hljs-attr">root</span>: sliderContainerRef.current,
    <span class="hljs-attr">threshold</span>: <span class="hljs-number">1.0</span>,
  });
  <span class="hljs-comment">// New Code</span>

  <span class="hljs-keyword">const</span> sliderItems = items || Children.toArray(children);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (sliderContainerRef.current) {
      <span class="hljs-keyword">const</span> sliderContainerWidth = sliderContainerRef.current.offsetWidth;

      <span class="hljs-keyword">const</span> elements = sliderContainerRef.current.querySelectorAll(<span class="hljs-string">'.slider-item'</span>);

      elements.forEach(<span class="hljs-function"><span class="hljs-params">el</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> sliderItemWidth = <span class="hljs-built_in">Math</span>.ceil((sliderContainerWidth / slidesPerView) - spaceBetween);

        el.style.width = sliderItemWidth + <span class="hljs-string">'px'</span>;

        <span class="hljs-built_in">Array</span>.from(el.children).forEach(<span class="hljs-function"><span class="hljs-params">elem</span> =&gt;</span> {
          elem.style.width = sliderItemWidth + <span class="hljs-string">'px'</span>;
        });

        setSliderItemWidth(sliderItemWidth);
      });
    }

  }, [slidesPerView, spaceBetween]);

  <span class="hljs-comment">// New Code</span>
  <span class="hljs-keyword">const</span> sliderButtonHandler = <span class="hljs-function">(<span class="hljs-params">direction</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"forward"</span>) {
      <span class="hljs-keyword">if</span> (!lastSliderItemInView &amp;&amp; activeSlideIndex &lt; (sliderItems.length - slidesPerGroup)) {
        setActiveSlideIndex(<span class="hljs-function">(<span class="hljs-params">prevIndex</span>) =&gt;</span> {
          <span class="hljs-keyword">if</span>((sliderItems.length - prevIndex) &lt; slidesPerGroup &amp;&amp; sliderItems.length - prevIndex != <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">return</span> sliderItems.length;
          }
          <span class="hljs-keyword">return</span> prevIndex + slidesPerGroup;
        });
      }
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"backward"</span>) {
      <span class="hljs-keyword">if</span> (!firstSliderItemInView &amp;&amp; activeSlideIndex &gt; <span class="hljs-number">0</span>) {
        setActiveSlideIndex(<span class="hljs-function">(<span class="hljs-params">prevIndex</span>) =&gt;</span> {
          <span class="hljs-keyword">if</span>(prevIndex &lt; slidesPerGroup) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
          }
          <span class="hljs-keyword">return</span> prevIndex - slidesPerGroup;
        });
      }
    }
  };

  <span class="hljs-keyword">const</span> setSliderItemRef = <span class="hljs-function">(<span class="hljs-params">index, sliderItemsArray</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (index === <span class="hljs-number">0</span>) {
      <span class="hljs-keyword">return</span> firstSliderItemRef;
    }
    <span class="hljs-keyword">if</span> (index === sliderItemsArray.length - <span class="hljs-number">1</span>) {
      <span class="hljs-keyword">return</span> lastSliderItemRef;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  };
  <span class="hljs-comment">// New Code</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slider}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slidesContainer}</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{sliderContainerRef}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> 
          <span class="hljs-attr">display:</span> "<span class="hljs-attr">flex</span>",
          <span class="hljs-attr">transition:</span> "<span class="hljs-attr">all</span> <span class="hljs-attr">0.5s</span> <span class="hljs-attr">ease-in-out</span>",
          <span class="hljs-attr">transform:</span> `<span class="hljs-attr">translateX</span>(${
            (<span class="hljs-attr">sliderItemWidth</span> + <span class="hljs-attr">spaceBetween</span>) * <span class="hljs-attr">activeSlideIndex</span> * <span class="hljs-attr">-1</span>
          }<span class="hljs-attr">px</span>)`,

          }}
        &gt;</span>
          {sliderItems.map((item, index, array) =&gt; {
            return (
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> 
                <span class="hljs-attr">className</span>=<span class="hljs-string">"slider-item"</span> 
                <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>
                <span class="hljs-attr">ref</span>=<span class="hljs-string">{setSliderItemRef(index,</span> <span class="hljs-attr">array</span>)}
                <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
                  <span class="hljs-attr">marginRight:</span> <span class="hljs-attr">Number</span>(<span class="hljs-attr">spaceBetween</span>)
                    ? `${<span class="hljs-attr">spaceBetween</span>}<span class="hljs-attr">px</span>`
                    <span class="hljs-attr">:</span> "<span class="hljs-attr">0px</span>",
                }}
              &gt;</span>
                {item}
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            );
          })}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonPrev</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("backward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">letterSpacing:</span> "<span class="hljs-attr">4px</span>" }}
        &gt;</span>
          arrow_back_ios_new
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonNext</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("forward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}&gt;</span>
          arrow_forward_ios
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Slider;
</code></pre>
<p>The updated code uses a custom <code>useInView</code> hook, which checks whether a slide is currently visible in the viewport.</p>
<p>Create a new file named <code>useInView.js</code> inside the <code>hooks</code> directory, and add the following code to it:</p>
<p><strong>useInView.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// useInView.js</span>
<span class="hljs-keyword">import</span> { useCallback, useEffect, useRef, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> useInView = <span class="hljs-function">(<span class="hljs-params">
  options = {
    root: <span class="hljs-literal">null</span>,
    rootMargin: <span class="hljs-string">"0px"</span>,
    threshold: <span class="hljs-number">1.0</span>,
  }
</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [inView, setInView] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> targetRef = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> inViewRef = useCallback(<span class="hljs-function">(<span class="hljs-params">node</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (node) {
      targetRef.current = node;
    }
  }, []);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> observer = <span class="hljs-keyword">new</span> IntersectionObserver(<span class="hljs-function">(<span class="hljs-params">entries</span>) =&gt;</span> {
      entries.forEach(<span class="hljs-function">(<span class="hljs-params">entry</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (entry.isIntersecting) {
          setInView(<span class="hljs-literal">true</span>);
        } <span class="hljs-keyword">else</span> {
          setInView(<span class="hljs-literal">false</span>);
        }
      });
    }, options);
    <span class="hljs-keyword">if</span> (targetRef.current) {
      observer.observe(targetRef.current);
    }
  }, [options]);

  <span class="hljs-keyword">return</span> { <span class="hljs-attr">ref</span>: targetRef, inView, inViewRef };
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useInView;
</code></pre>
<p>We’ve made quite a few changes to the code to make the carousel interactive. Let’s quickly review the changes one by one:</p>
<ul>
<li><p>We introduced a new state variable, <code>activeSlideIndex</code>, which keeps track of the index of the leftmost visible slide in the viewport.</p>
</li>
<li><p>We added a custom hook, <code>useInView</code>, that detects when a slide enters the viewport. This hook helps determine when the first or last slide becomes visible.</p>
</li>
<li><p>The <code>sliderButtonHandler</code> function has been updated to handle carousel navigation. It adjusts the <code>activeSlideIndex</code> based on whether the user clicks the forward or backward button.</p>
</li>
<li><p>Finally, we applied CSS <code>transform</code> to the slider container using the <code>translateX</code> function, which uses the <code>activeSlideIndex</code> to move the carousel forward or backward.</p>
</li>
</ul>
<h2 id="heading-autoplay-amp-loop">AutoPlay &amp; Loop</h2>
<p>Now that we’ve implemented basic navigation to move the carousel forward and backward using the navigation buttons, let’s make it more dynamic by adding autoplay and looping functionality.</p>
<p>These features will allow the carousel to automatically move to the next slide at regular intervals and loop back to the first slide once it reaches the end.</p>
<p>Update the <code>Slider.jsx</code> with the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Slider.jsx</span>
<span class="hljs-keyword">import</span> { Children, useState, useRef, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Slider.module.css"</span>;
<span class="hljs-keyword">import</span> useInView <span class="hljs-keyword">from</span> <span class="hljs-string">"../../hooks/useInView"</span>;

<span class="hljs-keyword">const</span> Slider = <span class="hljs-function">(<span class="hljs-params">{
  slidesPerView: initialSliderPerView = <span class="hljs-number">4</span>,
  spaceBetween: initialSpaceBetween = <span class="hljs-number">16</span>,
  slidesPerGroup: initialSliderPerGroup = <span class="hljs-number">4</span>,  
  items,
  children,
  loop,
  autoPlay = <span class="hljs-literal">false</span>,
  autoPlayInterval = <span class="hljs-number">2000</span>,
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [slidesPerView, setSlidesPerView] = useState(initialSliderPerView);
  <span class="hljs-keyword">const</span> [slidesPerGroup, setSlidesPerGroup] = useState(initialSliderPerGroup);
  <span class="hljs-keyword">const</span> [spaceBetween, setSpaceBetween] = useState(initialSpaceBetween);

  <span class="hljs-comment">// New Code</span>
  <span class="hljs-keyword">const</span> [activeSlideIndex, setActiveSlideIndex] = useState(
    loop ? slidesPerView : <span class="hljs-number">0</span>
  );
  <span class="hljs-keyword">const</span> [transitionEnabled, setTransitionEnabled] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-comment">// New Code</span>

  <span class="hljs-keyword">const</span> [sliderItemWidth, setSliderItemWidth] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">const</span> sliderContainerRef = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">const</span> { <span class="hljs-attr">inView</span>: lastSliderItemInView, <span class="hljs-attr">ref</span>: lastSliderItemRef } = useInView({
    <span class="hljs-attr">root</span>: sliderContainerRef.current,
    <span class="hljs-attr">threshold</span>: <span class="hljs-number">0.95</span>,
  });

  <span class="hljs-keyword">const</span> { <span class="hljs-attr">inView</span>: firstSliderItemInView, <span class="hljs-attr">ref</span>: firstSliderItemRef } = useInView({
    <span class="hljs-attr">root</span>: sliderContainerRef.current,
    <span class="hljs-attr">threshold</span>: <span class="hljs-number">1.0</span>,
  });


  items = items || Children.toArray(children);

  <span class="hljs-comment">// New Code</span>
  <span class="hljs-keyword">const</span> sliderItems = loop
    ? [
        ...items.slice(-slidesPerView),
        ...items,
        ...items.slice(<span class="hljs-number">0</span>, slidesPerView),
      ]
    : items;
  <span class="hljs-comment">// New Code</span>

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (sliderContainerRef.current) {
      <span class="hljs-keyword">const</span> sliderContainerWidth = sliderContainerRef.current.offsetWidth;

      <span class="hljs-keyword">const</span> elements = sliderContainerRef.current.querySelectorAll(<span class="hljs-string">'.slider-item'</span>);

      elements.forEach(<span class="hljs-function"><span class="hljs-params">el</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> sliderItemWidth = <span class="hljs-built_in">Math</span>.ceil((sliderContainerWidth / slidesPerView) - spaceBetween);

        el.style.width = sliderItemWidth + <span class="hljs-string">'px'</span>;

        <span class="hljs-built_in">Array</span>.from(el.children).forEach(<span class="hljs-function"><span class="hljs-params">div</span> =&gt;</span> {
          div.style.width = sliderItemWidth + <span class="hljs-string">'px'</span>;
        });

        setSliderItemWidth(sliderItemWidth);
      });
    }

  }, [slidesPerView, spaceBetween]);

  <span class="hljs-comment">// New Code</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      setTransitionEnabled(<span class="hljs-literal">true</span>);
    }, <span class="hljs-number">100</span>);
  }, [firstSliderItemRef]);


  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">let</span> intervalID;
    <span class="hljs-keyword">if</span> (loop &amp;&amp; autoPlay) {
      intervalID = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (
          activeSlideIndex === slidesPerGroup ||
          activeSlideIndex === items.length
        ) {
          setTransitionEnabled(<span class="hljs-literal">true</span>);
        }
        setActiveSlideIndex(<span class="hljs-function">(<span class="hljs-params">prevIndex</span>) =&gt;</span> prevIndex + slidesPerGroup);
      }, autoPlayInterval);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">if</span> (intervalID) {
        <span class="hljs-built_in">clearInterval</span>(intervalID);
      }
    };
  }, [
    loop,
    slidesPerGroup,
    activeSlideIndex,
    items.length,
    autoPlay,
    autoPlayInterval,
  ]);
  <span class="hljs-comment">// New Code</span>

  <span class="hljs-comment">// New Code</span>
  <span class="hljs-keyword">const</span> sliderButtonHandler = <span class="hljs-function">(<span class="hljs-params">direction</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (
      activeSlideIndex === slidesPerGroup ||
      activeSlideIndex === items.length
    ) {
      setTransitionEnabled(<span class="hljs-literal">true</span>);
    }
    <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"forward"</span>) {
      <span class="hljs-keyword">if</span> (loop || (!loop &amp;&amp; !lastSliderItemInView &amp;&amp; activeSlideIndex &lt; (items.length - slidesPerGroup))) {
        setActiveSlideIndex(<span class="hljs-function">(<span class="hljs-params">prevIndex</span>) =&gt;</span> {
          <span class="hljs-keyword">if</span>((items.length - prevIndex) &lt; slidesPerGroup &amp;&amp; items.length - prevIndex != <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">return</span> items.length;
          }
          <span class="hljs-keyword">return</span> prevIndex + slidesPerGroup;
        });
      }
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"backward"</span>) {
      <span class="hljs-keyword">if</span> (loop || (!loop &amp;&amp; !firstSliderItemInView &amp;&amp; activeSlideIndex &gt; <span class="hljs-number">0</span>)) {
        setActiveSlideIndex(<span class="hljs-function">(<span class="hljs-params">prevIndex</span>) =&gt;</span> {
          <span class="hljs-keyword">if</span>(prevIndex &lt; slidesPerGroup) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
          }
          <span class="hljs-keyword">return</span> prevIndex - slidesPerGroup;
        });
      }
    }
  };

  <span class="hljs-keyword">const</span> handleTransitionEnd = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (loop) {
      <span class="hljs-keyword">if</span> (activeSlideIndex &gt; items.length) {
        setTransitionEnabled(<span class="hljs-literal">false</span>);
        setActiveSlideIndex(slidesPerGroup);
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (activeSlideIndex === <span class="hljs-number">0</span>) {
        setTransitionEnabled(<span class="hljs-literal">false</span>);
        setActiveSlideIndex(items.length);
      }
    }
  };
  <span class="hljs-comment">// New Code</span>

  <span class="hljs-keyword">const</span> setSliderItemRef = <span class="hljs-function">(<span class="hljs-params">index, sliderItemsArray</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (loop &amp;&amp; index === <span class="hljs-number">0</span>) {
      <span class="hljs-keyword">return</span> firstSliderItemRef;
    }
    <span class="hljs-keyword">if</span> (!loop) {
      <span class="hljs-keyword">if</span> (index === <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">return</span> firstSliderItemRef;
      }
      <span class="hljs-keyword">if</span> (index === sliderItemsArray.length - <span class="hljs-number">1</span>) {
        <span class="hljs-keyword">return</span> lastSliderItemRef;
      }
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slider}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slidesContainer}</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{sliderContainerRef}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> 
          <span class="hljs-attr">onTransitionEnd</span>=<span class="hljs-string">{handleTransitionEnd}</span>
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
            <span class="hljs-attr">display:</span> "<span class="hljs-attr">flex</span>",
            <span class="hljs-attr">transition:</span> !<span class="hljs-attr">transitionEnabled</span> ? "<span class="hljs-attr">none</span>" <span class="hljs-attr">:</span> "<span class="hljs-attr">all</span> <span class="hljs-attr">0.5s</span> <span class="hljs-attr">ease-in-out</span>",
            <span class="hljs-attr">transform:</span> `<span class="hljs-attr">translateX</span>(${
              (<span class="hljs-attr">sliderItemWidth</span> + <span class="hljs-attr">spaceBetween</span>) * <span class="hljs-attr">activeSlideIndex</span> * <span class="hljs-attr">-1</span>
            }<span class="hljs-attr">px</span>)`,
          }}
        &gt;</span>
          {sliderItems.map((item, index, array) =&gt; {
            return (
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> 
                <span class="hljs-attr">className</span>=<span class="hljs-string">"slider-item"</span> 
                <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>
                <span class="hljs-attr">ref</span>=<span class="hljs-string">{setSliderItemRef(index,</span> <span class="hljs-attr">array</span>)}
                <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
                  <span class="hljs-attr">marginRight:</span> <span class="hljs-attr">Number</span>(<span class="hljs-attr">spaceBetween</span>)
                    ? `${<span class="hljs-attr">spaceBetween</span>}<span class="hljs-attr">px</span>`
                    <span class="hljs-attr">:</span> "<span class="hljs-attr">0px</span>",
                }}
              &gt;</span>
                {item}
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            );
          })}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonPrev</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("backward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">letterSpacing:</span> "<span class="hljs-attr">4px</span>" }}
        &gt;</span>
          arrow_back_ios_new
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonNext</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("forward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}&gt;</span>
          arrow_forward_ios
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Slider;
</code></pre>
<p>We have made a lot of changes to the component, let’s go through them one by one:</p>
<ul>
<li><p>The slider component now accepts three more props — <code>loop</code>, <code>autoPlay</code> and <code>autoPlayInterval</code>.</p>
</li>
<li><p>If looping is enabled, <code>sliderItems</code> becomes:</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> sliderItems = [
    ...items.slice(-slidesPerView),
    ...items,
    ...items.slice(<span class="hljs-number">0</span>, slidesPerView),
  ];
</code></pre>
</li>
<li><p>This allows the slider to simulate an infinite loop. When the user scrolls to the "end" or "start" of the carousel, the fake extra items allow a seamless visual transition back to the start or end, and the slider can be quickly repositioned behind the scenes.</p>
</li>
<li><p>The initial value of <code>activeSlideIndex</code> is set to the value of <code>slidesPerView</code> when looping is enabled.</p>
</li>
<li><p>The <code>sliderButtonHandler</code> function has been updated to handle looping behavior, adjusting the <code>activeSlideIndex</code> appropriately when navigating forward or backward</p>
</li>
<li><p>A new <code>useEffect</code> hook has been introduced to implement the autoplay functionality. It automatically updates the <code>activeSlideIndex</code> at a specified interval, moving the carousel forward without user interaction.</p>
</li>
<li><p>A <code>handleTransitionEnd</code> function has been added to temporarily remove the CSS transition from the slider container once the carousel reaches the end.</p>
</li>
<li><p>Another <code>useEffect</code> hook has been introduced that re-enables the transition when the first item becomes visible again, ensuring a smooth loop back to the beginning.</p>
</li>
</ul>
<p>Finally update the <code>App.jsx</code> to enable autoplay and looping:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Slider <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Slider/Slider'</span>;

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

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> sliderItems = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>, <span class="hljs-number">11</span>, <span class="hljs-number">12</span>];

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex-container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Slider</span>
            <span class="hljs-attr">slidesPerView</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">slidesPerGroup</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">spaceBetween</span>=<span class="hljs-string">{16}</span>
            <span class="hljs-attr">autoPlay</span>=<span class="hljs-string">{true}</span>
            <span class="hljs-attr">autoPlayInterval</span>=<span class="hljs-string">{2000}</span>
            <span class="hljs-attr">loop</span>=<span class="hljs-string">{true}</span>
          &gt;</span>
            {sliderItems.map((item, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"item"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>{item}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Slider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h2 id="heading-responsive-design">Responsive Design</h2>
<p>That was a lot of code we wrote, but there’s still one important piece of functionality that’s still missing — making the carousel responsive. Let’s finally add the code required to make it responsive across devices of different resolutions.</p>
<p>Update the <code>Slider.jsx</code> with the following code.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useRef, useState, useEffect, Children } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">import</span> useInView <span class="hljs-keyword">from</span> <span class="hljs-string">"../../hooks/useInView"</span>;
<span class="hljs-keyword">import</span> useWindowDimensions <span class="hljs-keyword">from</span> <span class="hljs-string">"../../hooks/useWindowDimensions"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Slider.module.css"</span>;

<span class="hljs-keyword">const</span> Slider = <span class="hljs-function">(<span class="hljs-params">{
  slidesPerView: initialSliderPerView,
  spaceBetween: initialSpaceBetween,
  slidesPerGroup: initialSliderPerGroup,
  loop,
  breakpoints,
  items,
  children,
  autoPlay = <span class="hljs-literal">false</span>,
  autoPlayInterval = <span class="hljs-number">2000</span>,
}</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [slidesPerView, setSlidesPerView] = useState(initialSliderPerView);
  <span class="hljs-keyword">const</span> [slidesPerGroup, setSlidesPerGroup] = useState(initialSliderPerGroup);
  <span class="hljs-keyword">const</span> [spaceBetween, setSpaceBetween] = useState(initialSpaceBetween);
  <span class="hljs-keyword">const</span> [activeSlideIndex, setActiveSlideIndex] = useState(
    loop ? slidesPerView : <span class="hljs-number">0</span>
  );
  <span class="hljs-keyword">const</span> [transitionEnabled, setTransitionEnabled] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [sliderItemWidth, setSliderItemWidth] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> sliderContainerRef = useRef(<span class="hljs-literal">null</span>);

  <span class="hljs-comment">// New Code</span>
  <span class="hljs-keyword">const</span> { <span class="hljs-attr">width</span>: deviceWidth } = useWindowDimensions();
  <span class="hljs-comment">// New Code</span>

  <span class="hljs-keyword">const</span> { <span class="hljs-attr">inView</span>: lastSliderItemInView, <span class="hljs-attr">ref</span>: lastSliderItemRef } = useInView({
    <span class="hljs-attr">root</span>: sliderContainerRef.current,
    <span class="hljs-attr">threshold</span>: <span class="hljs-number">0.95</span>,
  });

  <span class="hljs-keyword">const</span> { <span class="hljs-attr">inView</span>: firstSliderItemInView, <span class="hljs-attr">ref</span>: firstSliderItemRef } = useInView({
    <span class="hljs-attr">root</span>: sliderContainerRef.current,
    <span class="hljs-attr">threshold</span>: <span class="hljs-number">1.0</span>,
  });

  items = items || Children.toArray(children);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (sliderContainerRef.current) {
      <span class="hljs-keyword">const</span> sliderContainerWidth = sliderContainerRef.current.offsetWidth;

      <span class="hljs-keyword">const</span> elements = sliderContainerRef.current.querySelectorAll(<span class="hljs-string">'.slider-item'</span>);

      elements.forEach(<span class="hljs-function"><span class="hljs-params">el</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> sliderItemWidth = <span class="hljs-built_in">Math</span>.ceil((sliderContainerWidth / slidesPerView) - spaceBetween);

        el.style.width = sliderItemWidth + <span class="hljs-string">'px'</span>;

        <span class="hljs-built_in">Array</span>.from(el.children).forEach(<span class="hljs-function"><span class="hljs-params">div</span> =&gt;</span> {
          div.style.width = sliderItemWidth + <span class="hljs-string">'px'</span>;
        });

        setSliderItemWidth(sliderItemWidth);
      });
    }

  }, [slidesPerView, spaceBetween]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      setTransitionEnabled(<span class="hljs-literal">true</span>);
    }, <span class="hljs-number">100</span>);
  }, [firstSliderItemRef]);

 <span class="hljs-comment">// New Code</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (breakpoints) {
      <span class="hljs-built_in">Object</span>.keys(breakpoints).forEach(<span class="hljs-function">(<span class="hljs-params">breakpoint</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Number</span>(breakpoint) &amp;&amp; deviceWidth &gt;= <span class="hljs-built_in">Number</span>(breakpoint)) {
          setSlidesPerView(
            <span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> breakpoints[breakpoint].slidesPerView || prev
          );
          setSlidesPerGroup(
            <span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> breakpoints[breakpoint].slidesPerGroup || prev
          );
          setSpaceBetween(
            <span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> breakpoints[breakpoint].spaceBetween || prev
          );
          <span class="hljs-keyword">if</span>(loop) {
            setActiveSlideIndex(<span class="hljs-function">(<span class="hljs-params">prev</span>) =&gt;</span> breakpoints[breakpoint].slidesPerView || prev);
          }
        }
      });
    }
  }, [deviceWidth, breakpoints, loop]);
  <span class="hljs-comment">// New Code</span>

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">let</span> intervalID;
    <span class="hljs-keyword">if</span> (loop &amp;&amp; autoPlay) {
      intervalID = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (
          activeSlideIndex === slidesPerGroup ||
          activeSlideIndex === items.length
        ) {
          setTransitionEnabled(<span class="hljs-literal">true</span>);
        }
        setActiveSlideIndex(<span class="hljs-function">(<span class="hljs-params">prevIndex</span>) =&gt;</span> prevIndex + slidesPerGroup);
      }, autoPlayInterval);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">if</span> (intervalID) {
        <span class="hljs-built_in">clearInterval</span>(intervalID);
      }
    };
  }, [
    loop,
    slidesPerGroup,
    activeSlideIndex,
    items.length,
    autoPlay,
    autoPlayInterval,
  ]);

  <span class="hljs-keyword">const</span> sliderButtonHandler = <span class="hljs-function">(<span class="hljs-params">direction</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (
      activeSlideIndex === slidesPerGroup ||
      activeSlideIndex === items.length
    ) {
      setTransitionEnabled(<span class="hljs-literal">true</span>);
    }
    <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"forward"</span>) {
      <span class="hljs-keyword">if</span> (loop || (!loop &amp;&amp; !lastSliderItemInView &amp;&amp; activeSlideIndex &lt; (items.length - slidesPerGroup))) {
        setActiveSlideIndex(<span class="hljs-function">(<span class="hljs-params">prevIndex</span>) =&gt;</span> {
          <span class="hljs-keyword">if</span>((items.length - prevIndex) &lt; slidesPerGroup &amp;&amp; items.length - prevIndex != <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">return</span> items.length;
          }
          <span class="hljs-keyword">return</span> prevIndex + slidesPerGroup;
        });
      }
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (direction === <span class="hljs-string">"backward"</span>) {
      <span class="hljs-keyword">if</span> (loop || (!loop &amp;&amp; !firstSliderItemInView &amp;&amp; activeSlideIndex &gt; <span class="hljs-number">0</span>)) {
        setActiveSlideIndex(<span class="hljs-function">(<span class="hljs-params">prevIndex</span>) =&gt;</span> {
          <span class="hljs-keyword">if</span>(prevIndex &lt; slidesPerGroup) {
            <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
          }
          <span class="hljs-keyword">return</span> prevIndex - slidesPerGroup;
        });
      }
    }
  };

  <span class="hljs-keyword">const</span> handleTransitionEnd = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (loop) {
      <span class="hljs-keyword">if</span> (activeSlideIndex &gt; items.length) {
        setTransitionEnabled(<span class="hljs-literal">false</span>);
        setActiveSlideIndex(slidesPerGroup);
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (activeSlideIndex === <span class="hljs-number">0</span>) {
        setTransitionEnabled(<span class="hljs-literal">false</span>);
        setActiveSlideIndex(items.length);
      }
    }
  };

  <span class="hljs-keyword">const</span> sliderItems = loop
    ? [
        ...items.slice(-slidesPerView),
        ...items,
        ...items.slice(<span class="hljs-number">0</span>, slidesPerView),
      ]
    : items;

  <span class="hljs-keyword">const</span> setSliderItemRef = <span class="hljs-function">(<span class="hljs-params">index, sliderItemsArray</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (loop &amp;&amp; index === <span class="hljs-number">0</span>) {
      <span class="hljs-keyword">return</span> firstSliderItemRef;
    }
    <span class="hljs-keyword">if</span> (!loop) {
      <span class="hljs-keyword">if</span> (index === <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">return</span> firstSliderItemRef;
      }
      <span class="hljs-keyword">if</span> (index === sliderItemsArray.length - <span class="hljs-number">1</span>) {
        <span class="hljs-keyword">return</span> lastSliderItemRef;
      }
    }
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slider}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.slidesContainer}</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{sliderContainerRef}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
          <span class="hljs-attr">onTransitionEnd</span>=<span class="hljs-string">{handleTransitionEnd}</span>
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
            <span class="hljs-attr">display:</span> "<span class="hljs-attr">flex</span>",
            <span class="hljs-attr">transition:</span> !<span class="hljs-attr">transitionEnabled</span> ? "<span class="hljs-attr">none</span>" <span class="hljs-attr">:</span> "<span class="hljs-attr">all</span> <span class="hljs-attr">0.5s</span> <span class="hljs-attr">ease-in-out</span>",
            <span class="hljs-attr">transform:</span> `<span class="hljs-attr">translateX</span>(${
              (<span class="hljs-attr">sliderItemWidth</span> + <span class="hljs-attr">spaceBetween</span>) * <span class="hljs-attr">activeSlideIndex</span> * <span class="hljs-attr">-1</span>
            }<span class="hljs-attr">px</span>)`,
            <span class="hljs-attr">marginBottom:</span> "<span class="hljs-attr">3px</span>",
          }}
        &gt;</span>
          {sliderItems.map((item, index, array) =&gt; {
            return (
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"slider-item"</span> 
                <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>
                <span class="hljs-attr">ref</span>=<span class="hljs-string">{setSliderItemRef(index,</span> <span class="hljs-attr">array</span>)}
                <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
                  <span class="hljs-attr">marginRight:</span> <span class="hljs-attr">Number</span>(<span class="hljs-attr">spaceBetween</span>)
                    ? `${<span class="hljs-attr">spaceBetween</span>}<span class="hljs-attr">px</span>`
                    <span class="hljs-attr">:</span> "<span class="hljs-attr">0px</span>",
                }}
              &gt;</span>
                {item}
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            );
          })}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonPrev</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("backward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">letterSpacing:</span> "<span class="hljs-attr">4px</span>" }}
        &gt;</span>
          arrow_back_ios_new
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">styles.slideButton</span>} ${<span class="hljs-attr">styles.slideButtonNext</span>}`}
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> sliderButtonHandler("forward")}
      &gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">material-symbols-outlined</span> ${<span class="hljs-attr">styles.slideButtonIcon</span>}`}&gt;</span>
          arrow_forward_ios
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Slider;
</code></pre>
<p>Create a new file named <code>useWindowDimensions.js</code> inside the <code>hooks</code> directory and add the following code to it:</p>
<p><strong>useWindowDimensions.js</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getWindowDimensions</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { <span class="hljs-attr">innerWidth</span>: width, <span class="hljs-attr">innerHeight</span>: height } = <span class="hljs-built_in">window</span>;
  <span class="hljs-keyword">return</span> {
    width,
    height,
  };
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useWindowDimensions</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [windowDimensions, setWindowDimensions] = useState(
    getWindowDimensions()
  );

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleResize</span>(<span class="hljs-params"></span>) </span>{
      setWindowDimensions(getWindowDimensions());
    }

    <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">"resize"</span>, handleResize);
    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">window</span>.removeEventListener(<span class="hljs-string">"resize"</span>, handleResize);
  }, []);

  <span class="hljs-keyword">return</span> windowDimensions;
}
</code></pre>
<p>Let’s quickly go through the changes we made one by one:</p>
<ul>
<li><p>The updated code uses another custom <code>useWindowDimensions</code> hook, which returns the height and width of the browser window both when it is first initialized and whenever the window is resized.</p>
</li>
<li><p>The component now accepts one additional prop — <code>breakpoints</code>, an object that defines how many items should be visible in the carousel based on the device’s screen width.</p>
</li>
<li><p>Each key in the <code>breakpoints</code> object (e.g., <code>320</code>, <code>768</code>, <code>1366</code>) represents a <strong>minimum</strong> viewport width (in pixels). The corresponding value defines the layout configuration at that width.</p>
</li>
<li><p>A new <code>useEffect</code> hook has been added to dynamically update the <code>slidesPerView</code>, <code>slidesPerGroup</code>, and <code>spaceBetween</code> values according to the current screen width, if the <code>breakpoints</code> prop is provided</p>
</li>
</ul>
<p>Finally update the <code>App.jsx</code> to enable responsive behavior:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Slider <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Slider/Slider'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> sliderItems = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>, <span class="hljs-number">11</span>, <span class="hljs-number">12</span>];

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex-container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Slider</span>
            <span class="hljs-attr">spaceBetween</span>=<span class="hljs-string">{16}</span>
            <span class="hljs-attr">slidesPerView</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">slidesPerGroup</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">loop</span>=<span class="hljs-string">{true}</span>
            <span class="hljs-attr">autoPlay</span>=<span class="hljs-string">{true}</span>
            <span class="hljs-attr">autoPlayInterval</span>=<span class="hljs-string">{4000}</span>
            <span class="hljs-attr">breakpoints</span>=<span class="hljs-string">{{</span>
              <span class="hljs-attr">320:</span> {
                <span class="hljs-attr">slidesPerView:</span> <span class="hljs-attr">1</span>,
                <span class="hljs-attr">slidesPerGroup:</span> <span class="hljs-attr">1</span>,
              },
              <span class="hljs-attr">1366:</span> {
                <span class="hljs-attr">slidesPerView:</span> <span class="hljs-attr">4</span>,
                <span class="hljs-attr">slidesPerGroup:</span> <span class="hljs-attr">4</span>,
                <span class="hljs-attr">spaceBetween:</span> <span class="hljs-attr">18</span>
              },
            }}
          &gt;</span>
            {sliderItems.map((item, index) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"item"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>{item}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            ))}
          <span class="hljs-tag">&lt;/<span class="hljs-name">Slider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h2 id="heading-final-result">Final Result</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=m-b9jZ0-z0I&amp;feature=youtu.be">https://www.youtube.com/watch?v=m-b9jZ0-z0I&amp;feature=youtu.be</a></div>
<p> </p>
<h2 id="heading-source-code">Source Code</h2>
<p>You can download the source code from my GitHub repo:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/SukhjinderArora/react-carousel">https://github.com/SukhjinderArora/react-carousel</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we walked through building a fully functional, customizable, and responsive carousel component in React from scratch. Starting with a basic layout, we incrementally added key features like navigation controls, autoplay and loop.</p>
<p>Finally, we implemented responsive behavior using the <code>breakpoints</code> prop, allowing the carousel to adapt seamlessly to different screen sizes and device resolutions.</p>
<p>By now, you should have a solid understanding of how to build a flexible carousel component that can be reused and extended in your own projects.</p>
<p>That’s it and hope you found this article helpful! Please feel free to comment below and ask anything, suggest feedback or just chat. You can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora"><strong>Hashnode</strong></a>, <a target="_blank" href="https://medium.com/@sukhjinder"><strong>Medium</strong></a> and <a target="_blank" href="https://twitter.com/sukhjinder_95"><strong>Twitter</strong></a>. Cheers! ⭐️</p>
]]></content:encoded></item><item><title><![CDATA[React and NodeJS Authentication with Refresh & Access Tokens: A Step-by-Step Guide]]></title><description><![CDATA[The most common way of performing authentication in Single Page Applications (SPA) is through the use of JSON Web Tokens (JWT). While JWT-based authentication is easy to implement, there are some downsides to using JWT in SPAs that should be consider...]]></description><link>https://whatisweb.dev/react-and-nodejs-authentication-with-refresh-access-tokens-a-step-by-step-guide</link><guid isPermaLink="true">https://whatisweb.dev/react-and-nodejs-authentication-with-refresh-access-tokens-a-step-by-step-guide</guid><category><![CDATA[React]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[authentication]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Tue, 30 May 2023 14:28:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/L8KQIPCODV8/upload/6d50901f5f9ce79b4d6ab523266e5bfd.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The most common way of performing authentication in Single Page Applications (SPA) is through the use of JSON Web Tokens (JWT). While JWT-based authentication is easy to implement, there are some downsides to using JWT in SPAs that should be considered:</p>
<ol>
<li><p><strong>Security</strong>: Since JWT is stateless and does not store any information on the server, there's no way to invalidate it from the server side. If a JWT is stolen or compromised, an attacker can gain access to sensitive information.</p>
</li>
<li><p><strong>Lack of Revocation</strong>: As JWT is stateless, it makes it difficult to revoke tokens from the server side when a user logs out or changes their password, or to allow users to sign out from all devices.</p>
</li>
<li><p><strong>Limited Validity Period</strong>: As JWT is valid for a limited amount of time, the users will have to log in to the application whenever the JWT expires, which is not a good user experience.</p>
</li>
</ol>
<p>We can avoid these issues either by <strong>1)</strong> Using Sessions, or <strong>2)</strong> Using Refresh and Access tokens to authenticate users, which I will cover in this article.</p>
<p>Before getting started, let's first understand what refresh and access tokens are.</p>
<p><strong>What are Access Tokens?</strong></p>
<p>Access tokens are short-lived tokens that are issued by an authorization server and are used to access protected resources. Access tokens are passed in the header of an API request and are used to verify that the user has the necessary permissions to access the requested resource.</p>
<p><strong>What are Refresh Tokens?</strong></p>
<p>Refresh tokens are long-lived tokens that are issued along with access tokens. They are used to request a new access token when the current access token expires. This allows the user to remain authenticated even if the access token has expired, without having to re-enter their credentials.</p>
<h3 id="heading-getting-started">Getting Started</h3>
<p>Before starting, you must have npm installed on your computer, which comes bundled with <a target="_blank" href="https://nodejs.org/en/">Node.js</a> which you can install from <a target="_blank" href="https://nodejs.org/en/download/">here</a>.</p>
<p><strong>Folder Structure:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676368743189/3d01b1a2-cef7-4788-a2e4-d6aad4d86afd.png" alt class="image--center mx-auto" /></p>
<p>You can create the above directories with these commands.</p>
<pre><code class="lang-javascript">mkdir refresh-token-auth-app
cd refresh-token-auth-app
mkdir client server
</code></pre>
<p>This project is divided into two parts:</p>
<ol>
<li><p>Node.js &amp; Express application for the backend.</p>
</li>
<li><p>ReactJS application for the front end.</p>
</li>
</ol>
<p><strong>Creating Backend Application:</strong></p>
<p>Run the following commands to initialize the Node.js project and install the required dependencies.</p>
<pre><code class="lang-javascript">cd refresh-token-auth-app/server
npm init -y
npm install express jsonwebtoken cookie-parser cors dotenv ms http-errors
</code></pre>
<p><strong>Creating Frontend Application:</strong></p>
<p>Run the following commands to initialize the React project.</p>
<pre><code class="lang-javascript">cd refresh-token-auth-app
npx create-react-app client
</code></pre>
<h3 id="heading-authentication-flow">Authentication Flow</h3>
<p>Now that we have set up the project structure required for the application, let's understand the general overview of how the refresh and access token-based authentication will work in our application.</p>
<ol>
<li><p>When a user first logs in to our application, the server will generate an access token and a refresh token for the user. The access token will be sent as a part of the response body, while the refresh token will be sent as an <code>httpOnly</code> cookie. The refresh token will also be stored in the database for each user.</p>
</li>
<li><p>When the access token is about to expire, our application will automatically send a request to the server to refresh the access token, also known as <strong>silent authentication</strong>. Since we are storing the access token in memory instead of local storage to prevent XSS attacks, our application will also perform silent authentication when the user refreshes the browser window.</p>
</li>
<li><p>When a user logs out of the application, the server will remove the refresh token stored in the database and the cookie.</p>
</li>
</ol>
<h3 id="heading-api-endpoints">API Endpoints</h3>
<p>Now that we have a basic understanding of the authentication flow of our application, let's list the API endpoints necessary for the application to work.</p>
<p>We will need these endpoints to make our application work.</p>
<ol>
<li><p><code>POST - /auth/sign-up</code> to allow users to sign up.</p>
</li>
<li><p><code>POST - /auth/login</code> to allow users to log in.</p>
</li>
<li><p><code>POST - /auth/refresh</code> to generate a new access token using the given refresh token.</p>
</li>
<li><p><code>POST - /auth/logout</code> to log out the user.</p>
</li>
<li><p><code>GET - /users/list</code> (optional) to get the list of users.</p>
</li>
</ol>
<h3 id="heading-folder-structure">Folder Structure</h3>
<p>Before we start writing these APIs, let's create the folder structure required for the backend application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685627007989/b94857ba-c345-4d2a-aec1-920a81c3b952.png" alt class="image--center mx-auto" /></p>
<p>You can create the above directories with these commands.</p>
<pre><code class="lang-javascript">cd server
mkdir controllers middlewares routes data utils
touch app.js
</code></pre>
<h3 id="heading-creating-express-application">Creating Express Application</h3>
<p>Add the following boilerplate code to the <code>app.js</code> file to create the express application.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>);
<span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config();

<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> cors = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cors'</span>);
<span class="hljs-keyword">const</span> cookieParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cookie-parser'</span>);

<span class="hljs-keyword">const</span> { PORT, NODE_ENV } = process.env;

<span class="hljs-keyword">const</span> isDev = NODE_ENV === <span class="hljs-string">'development'</span>;

<span class="hljs-keyword">const</span> app = express();

<span class="hljs-keyword">if</span> (isDev) {
    app.use(
        cors({
            <span class="hljs-attr">origin</span>: <span class="hljs-string">'http://localhost:3000'</span>,
            <span class="hljs-attr">optionsSuccessStatus</span>: <span class="hljs-number">200</span>,
            <span class="hljs-attr">credentials</span>: <span class="hljs-literal">true</span>,
        })
    );
}

app.use(express.json({ <span class="hljs-attr">type</span>: <span class="hljs-string">'application/json'</span> }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(express.static(path.join(__dirname, <span class="hljs-string">'public'</span>)));

app.get(<span class="hljs-string">'*'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.sendFile(path.resolve(__dirname, <span class="hljs-string">'public'</span>, <span class="hljs-string">'index.html'</span>));
});

app.use(<span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> error = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Not Found'</span>);
    error.status = <span class="hljs-number">404</span>;
    next(error);
});

app.use(<span class="hljs-function">(<span class="hljs-params">error, req, res, next</span>) =&gt;</span> {
   <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"\x1b[31m"</span>, error);
   <span class="hljs-keyword">if</span> (res.headersSent) {
        <span class="hljs-keyword">return</span> next(error);
    }
    <span class="hljs-keyword">return</span> res.status(error.status || <span class="hljs-number">500</span>).json({
        <span class="hljs-attr">error</span>: {
            <span class="hljs-attr">status</span>: error.status || <span class="hljs-number">500</span>,
            <span class="hljs-attr">message</span>: error.status ? error.message : <span class="hljs-string">"Internal Server Error"</span>,
        },
    });
});

app.listen(PORT || <span class="hljs-number">5000</span>, <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (error) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Error in server setup"</span>);
        <span class="hljs-keyword">return</span>;
    }
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Server listening on Port"</span>, PORT);
});
</code></pre>
<p>Here I am using:</p>
<ol>
<li><p><code>dotenv</code> middleware to load environment variables from the <code>.env</code> file into the <code>process.env</code> variable.</p>
</li>
<li><p><code>cors</code> middleware to allow Cross-Origin Resource Sharing (CORS) in development mode.</p>
</li>
<li><p><code>express.json</code> to parse the request body as JSON.</p>
</li>
<li><p><code>cookie-parser</code> middleware to parse cookies in the incoming request headers.</p>
</li>
<li><p><code>express.static</code> middleware to serve the static files from the <code>public</code> directory.</p>
</li>
<li><p>Error handler middleware — which is executed when an error occurs in the application.</p>
</li>
<li><p>And Finally <code>app.listen</code> method to create a new server and listen on the specified port defined by the <code>PORT</code> environment variable.</p>
</li>
</ol>
<p>Add this code to the <code>package.json</code> script section:</p>
<pre><code class="lang-javascript"><span class="hljs-string">"start"</span>: <span class="hljs-string">"node app.js"</span>
</code></pre>
<p><strong>Environment variables</strong></p>
<p>Create a <code>.env</code> file at the root of the <code>server</code> directory and add the following environment variables to that file.</p>
<pre><code class="lang-javascript">PORT=<span class="hljs-number">5000</span>

ACCESS_TOKEN_SECRET=<span class="hljs-number">7</span>rG7v5ElkhMpIHdQfs5l4sC+zprSYD2DNII4fzRusLevT2n0fEvpFzd6Ei2GpXzwEkghDxWxONRx0eCvcrsziY6EuF6GutZX+niTT6QJylTba/ydgURY9+<span class="hljs-number">7</span>k1rn8w7sfiCAQPBg7c/SlY/nMRsDF4/<span class="hljs-number">5</span>MSQATlfuSXX+<span class="hljs-number">9</span>BIKgDmFWwZA19QqGS4cWKNiQO7JEhcNjkpy0FtaeUzK1/q0pG5Rjq8V8L8zbyhttUbAWd3h8N+m5vV7gi22HBrLlqpbFL0IIeb3GHWEe9z1nymyQNjLdxO6kcNRBNmWR7nRbamje6TJ6aHChebONL5h3GRWAFLwS188L41iNp67EqcNSqg==

REFRESH_TOKEN_SECRET=LbIiOVV6MuKQ7A2KnGi6uW6vxrypJrouog48VY4bJjrJJdBbq0XLuKBU4Ia/Pzphvk4j6iUa7EEFnpgCBRewvxPCIyHZpHrGRZjUtCmbjGpLqIe5tlgMlEOPTzrwYAkgAHBNN6UzeZl55wlzOSiCWbhqcw2V6qDy8KYh+llIm/eBUVVlThNw7TDsn0LtcLBjhkzaBQqCUzZQmOLtTpCerjnzaWzlS2vSyP96zJ/yemlkgF21EZkiKPdoNrJPeaXNk4kqECHNlZ4mccpCTSWPr+RPR/vjGltCRL6nhJ1w6MqBDYFpXcAHcv54fz1bXcEwkhEO5imzoKa6aMg/<span class="hljs-number">1</span>LPpTw==

COOKIE_SECRET=Ak1jjwP38UQ3TUPatxFva2tytaYx0HnKxkfytoQAoignerppxxg7ogh2tUxnKhSe0JXVL7kbAZsHcnCFE3hY3OI2nuydrR9JL/xrj30EFBSQNjQ7FK8rY8S0QES/<span class="hljs-number">5</span>z28k+etbBd9u7ms/bo/+YuA2ueJ2MiFCeRNH7UGknueF3JHEa+sfSVsf3QLIBgXd2WwmemRNYeqtpRmdxY29t8HeDwJqtoY9WdLU2onahQCzyuzD2/<span class="hljs-number">5</span>aJWwwSIGyL7VeHSg7BQ/DDK+s2tv/IP6LVr3kVGMwhOGJksh6N5Ndeh9p22BkxsN4Nw1jzlxRGN4OhNmLdiPkFsAzj2B739z87mwNQ==

ACCESS_TOKEN_LIFE=<span class="hljs-number">15</span>m

REFRESH_TOKEN_LIFE=<span class="hljs-number">30</span>d
</code></pre>
<p>You can generate these secret keys in NodeJS console / REPL (Read Evaluate Print Loop) using:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">require</span>(<span class="hljs-string">'crypto'</span>).randomBytes(<span class="hljs-number">256</span>).toString(<span class="hljs-string">'base64'</span>);
</code></pre>
<p>Because the access token is meant to be short-lived, It has been set to expire after 15 minutes. The refresh token is meant to remain valid for a longer duration, so its expiration time has been set to 30 days.</p>
<h3 id="heading-adding-dummy-data">Adding Dummy Data</h3>
<p>For the sake of simplicity, I am not using any database in this article, so let's create a new <code>data.js</code> file inside the data folder. This file contains the dummy data required for the application to function.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// data.js</span>
<span class="hljs-keyword">const</span> users = [
    {
        <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">"John Doe"</span>,
        <span class="hljs-attr">email</span>: <span class="hljs-string">"johndoe@example.com"</span>,
        <span class="hljs-attr">userName</span>: <span class="hljs-string">"johndoe"</span>,
        <span class="hljs-attr">password</span>: <span class="hljs-string">"JohnDoe@123"</span>
    },
    {
        <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>,
        <span class="hljs-attr">name</span>: <span class="hljs-string">"Jane Smith"</span>,
        <span class="hljs-attr">email</span>: <span class="hljs-string">"janesmith@example.com"</span>,
        <span class="hljs-attr">userName</span>: <span class="hljs-string">"janesmith"</span>,
        <span class="hljs-attr">password</span>: <span class="hljs-string">"JaneSmith@123"</span>
    },
];

<span class="hljs-keyword">const</span> tokens = [];  <span class="hljs-comment">// [{userId: number, refreshToken: string, expirationTime: number }]</span>

<span class="hljs-built_in">module</span>.exports = { users, tokens };
</code></pre>
<p>Here, the <code>users</code> array is used to store the application's users and the <code>tokens</code> array is used to store the users' refresh tokens along with their user ID and the token's expiration time.</p>
<p><strong>Note:—</strong> I am storing the passwords as plain text, but you should not store them as plain text for real-world applications.</p>
<h3 id="heading-adding-routes-controllers-and-middlewares">Adding Routes, Controllers and Middlewares</h3>
<p><strong>Adding Auth Routes</strong></p>
<p>Add this code to the <code>auth.js</code> file inside the <code>routes</code> folder.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> router = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>).Router();

<span class="hljs-keyword">const</span> authController = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../controllers/auth'</span>);
<span class="hljs-keyword">const</span> authMiddleware = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../middlewares/auth'</span>);

router.post(
    <span class="hljs-string">'/sign-up'</span>,
    authController.signUp,
    authMiddleware.generateAuthTokens
);

router.post(
    <span class="hljs-string">'/login'</span>,
    authController.login,
    authMiddleware.generateAuthTokens
);

router.post(
    <span class="hljs-string">'/logout'</span>,
    authMiddleware.isAuthenticated,
    authController.logout
);

router.post(
    <span class="hljs-string">'/refresh'</span>,
    authController.refreshAccessToken
);

<span class="hljs-built_in">module</span>.exports = router;
</code></pre>
<ol>
<li><p><code>POST /auth/sign-up</code>: This endpoint handles the sign-up requests. It uses the <code>authController.signUp</code> method to create a new user account, and then uses the <code>authMiddleware.generateAuthTokens</code> middleware to generate authentication tokens for the user.</p>
</li>
<li><p><code>POST /auth/login</code>: This endpoint handles the login requests. It uses the <code>authController.login</code> method to authenticate the user, and then uses the <code>authMiddleware.generateAuthTokens</code> middleware to generate authentication tokens for the user.</p>
</li>
<li><p><code>POST /auth/logout</code>: This endpoint handles user logout requests. It uses the <code>authMiddleware.isAuthenticated</code> middleware to check if the user is authenticated, and then uses the <code>authController.logout</code> method to log out the user.</p>
</li>
<li><p><code>POST /auth/refresh</code>: This endpoint is used to refresh the access token. When the access token expires, the client can use this endpoint to obtain a new access token by sending a valid refresh token in the request body. The <code>authController.refreshAccessToken</code> function is called to handle this request and generate a new access token.</p>
</li>
</ol>
<p><strong>Adding Users Routes</strong></p>
<p>Add this code to the <code>users.js</code> file inside the <code>routes</code> folder.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> router = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>).Router();

<span class="hljs-keyword">const</span> { isAuthenticated } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../middlewares/auth'</span>);

<span class="hljs-keyword">const</span> usersController = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../controllers/users'</span>);

router.get(<span class="hljs-string">'/list'</span>, isAuthenticated, usersController.getUsersList);

router.get(<span class="hljs-string">'/me'</span>, isAuthenticated, usersController.getAuthenticatedUser);

router.get(<span class="hljs-string">'/:id'</span>, isAuthenticated, usersController.getUserById);

<span class="hljs-built_in">module</span>.exports = router;
</code></pre>
<ol>
<li><p><code>GET /users/list</code>: This endpoint is used to retrieve the list of users. It uses the <code>authMiddleware.isAuthenticated</code> middleware to check if the user is authenticated, and then uses the <code>usersController.getUsersList</code> method to get the list of users.</p>
</li>
<li><p><code>GET /users/me</code>: This endpoint is used to retrieve the authenticated user's information. It uses the <code>authMiddleware.isAuthenticated</code> middleware to check if the user is authenticated, and then uses the <code>usersController.getAuthenticatedUser</code> method to get the authenticated user.</p>
</li>
<li><p><code>GET /users/:id</code>: This endpoint is used to retrieve a user's information by ID. It uses the <code>authMiddleware.isAuthenticated</code> middleware to check if the user is authenticated, and then uses the <code>usersController.getUserById</code> method to get the user by their ID. The user's ID is specified in the URL path using a route parameter (<code>:id</code>).</p>
</li>
</ol>
<p><strong>Updating</strong> <code>app.js</code>:</p>
<p>Add this code inside <code>app.js</code> to add the <code>auth</code> and <code>users</code> routes.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/**
 * Existing Code
 */</span>
<span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>);
<span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config();

<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> cors = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cors'</span>);
<span class="hljs-keyword">const</span> cookieParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">'cookie-parser'</span>);

<span class="hljs-comment">/**
 * New Code
 */</span>
<span class="hljs-keyword">const</span> authRoutes = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./routes/auth'</span>);
<span class="hljs-keyword">const</span> usersRoutes = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./routes/users'</span>);

<span class="hljs-comment">/**
 * Existing Code
 */</span>
<span class="hljs-keyword">const</span> { PORT, NODE_ENV } = process.env;

<span class="hljs-keyword">const</span> isDev = NODE_ENV === <span class="hljs-string">'development'</span>;

<span class="hljs-keyword">const</span> app = express();

<span class="hljs-keyword">if</span> (isDev) {
    app.use(
        cors({
            <span class="hljs-attr">origin</span>: <span class="hljs-string">'http://localhost:3000'</span>,
            <span class="hljs-attr">optionsSuccessStatus</span>: <span class="hljs-number">200</span>,
            <span class="hljs-attr">credentials</span>: <span class="hljs-literal">true</span>,
        })
    );
}

app.use(express.json({ <span class="hljs-attr">type</span>: <span class="hljs-string">'application/json'</span> }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(express.static(path.join(__dirname, <span class="hljs-string">'public'</span>)));

<span class="hljs-comment">/**
 * New Code
 */</span>
app.use(<span class="hljs-string">'/api/auth'</span>, authRoutes);
app.use(<span class="hljs-string">'/api/users'</span>, usersRoutes);
</code></pre>
<p><strong>Adding Auth Controllers</strong></p>
<p>Add this code to the <code>auth.js</code> file inside the <code>controllers</code> folder.</p>
<p><strong>Sign-up Controller</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> createError = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http-errors'</span>);

<span class="hljs-keyword">const</span> { users } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../data/data'</span>);

<span class="hljs-keyword">const</span> signUp = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">const</span> { name, username, email, password } = req.body;

    <span class="hljs-keyword">if</span>(!name || !username || !email || !password) {
        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">422</span>).json({
            <span class="hljs-attr">error</span>: <span class="hljs-string">'Please fill all the required fields'</span>
        });
    }

    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> userAlreadyExists = users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
            <span class="hljs-keyword">if</span> (user.userName === username || user.email === email) {
                <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
            }
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        });

        <span class="hljs-keyword">if</span> (userAlreadyExists) {
            <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">422</span>).json({
                <span class="hljs-attr">error</span>: <span class="hljs-string">'Username or email already exists'</span>
            });
        }

        <span class="hljs-keyword">const</span> newUser = {
            <span class="hljs-attr">id</span>: users[users.length - <span class="hljs-number">1</span>].id + <span class="hljs-number">1</span>,
            <span class="hljs-attr">name</span>: name,
            <span class="hljs-attr">userName</span>: username,
            <span class="hljs-attr">email</span>: email,
            <span class="hljs-attr">password</span>: password
        };

        users.push(newUser);

        req.userId = newUser.id;
        <span class="hljs-keyword">return</span> next();
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-keyword">return</span> next(error);
    }
};

<span class="hljs-built_in">module</span>.exports = {
    signUp
}
</code></pre>
<p>The <code>signUp</code> function is responsible for handling the sign-up process. It requires the user's name, username, email, and password to be sent in the request body. It then checks if all the required fields are present, and if not, it returns a response with a <code>422</code> status code and an error message.</p>
<p>Next, it checks if a user with the same <code>username</code> or <code>email</code> already exists in the <code>users</code> array. If it does, it returns a response with a <code>422</code> status code and an error message indicating that the username or email already exists.</p>
<p>If the user does not already exist, the function creates a new user object with the required fields, assigns it a unique <code>id</code>, and pushes it to the <code>users</code> array.</p>
<p>The function then sets the <code>userId</code> property of the <code>req</code> object to the newly created user's <code>id</code> and calls the <code>next</code> function to pass control to the next middleware to generate the authentication tokens for the user.</p>
<p>If any error occurs during the execution of the function, it calls the <code>next</code> function with the error to pass control to the error-handling middleware.</p>
<p><strong>Login Controller</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> createError = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http-errors'</span>);

<span class="hljs-keyword">const</span> { users } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../data/data'</span>);

<span class="hljs-keyword">const</span> signUp = <span class="hljs-keyword">async</span> (req, res, next) =&gt; { .... };

<span class="hljs-keyword">const</span> login = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">const</span> { username, password } = req.body;

    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">if</span> (!username || !password) {
            <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">422</span>).json({
                <span class="hljs-attr">error</span>: <span class="hljs-string">'Please fill all the required fields'</span>
            });
        }

        <span class="hljs-keyword">const</span> user = users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
            <span class="hljs-keyword">if</span> (user.userName === username || user.email === username) {
                <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
            }
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        });

        <span class="hljs-keyword">if</span> (!user) {
            <span class="hljs-keyword">const</span> error = createError.Unauthorized(<span class="hljs-string">'Invalid username or password'</span>);
            <span class="hljs-keyword">throw</span> error;
        }

        <span class="hljs-keyword">const</span> passwordsMatch = user.password == password;

        <span class="hljs-keyword">if</span> (!passwordsMatch) {
            <span class="hljs-keyword">const</span> error = createError.Unauthorized(<span class="hljs-string">'Invalid username or password'</span>);
            <span class="hljs-keyword">throw</span> error;
        }

        req.userId = user.id;
        <span class="hljs-keyword">return</span> next();
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-keyword">return</span> next(error);
    }
};

<span class="hljs-built_in">module</span>.exports = {
    signUp,
    login
}
</code></pre>
<p>The <code>login</code> function is responsible for handling the log-in process. It requires the user's username and password to be sent in the request body. If either of these fields is missing, it sends an error response back to the client indicating that both fields are required.</p>
<p>Next, the function searches for a user in the <code>users</code> array by checking if either the <code>userName</code> or <code>email</code> of the user matches the provided <code>username</code>. If a matching user is found, the function checks if the provided <code>password</code> matches the user's password.</p>
<p>If the provided <code>password</code> does not match, the function sends an error response indicating that the username or password is invalid. If the provided <code>password</code> matches, the function then sets the <code>userId</code> property of the <code>req</code> object to the authenticated user's <code>id</code> and calls the <code>next</code> function to pass control to the next middleware to generate the authentication tokens for the user.</p>
<p>If any error occurs during the execution of the function, it calls the <code>next</code> function with the error to pass control to the error-handling middleware.</p>
<p><strong>Logout Controller</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);
<span class="hljs-keyword">const</span> createError = <span class="hljs-built_in">require</span>(<span class="hljs-string">"http-errors"</span>);
<span class="hljs-keyword">const</span> ms = <span class="hljs-built_in">require</span>(<span class="hljs-string">'ms'</span>);

<span class="hljs-keyword">const</span> { clearTokens, generateJWT } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../utils/auth"</span>);
<span class="hljs-keyword">const</span> { users, tokens } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../data/data"</span>);

<span class="hljs-keyword">const</span> signUp = <span class="hljs-keyword">async</span> (req, res, next) =&gt; { .... };

<span class="hljs-keyword">const</span> login = <span class="hljs-keyword">async</span> (req, res, next) =&gt; { .... };

<span class="hljs-keyword">const</span> logout = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
  <span class="hljs-keyword">await</span> clearTokens(req, res, next);
  <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">204</span>);
};

<span class="hljs-built_in">module</span>.exports = {
    signUp,
    login,
    logout
};
</code></pre>
<p>The <code>logout</code> function is responsible for logging out the user. It does so by calling the <code>clearTokens</code> function to remove the user's refresh token from the server as well as from the user's cookie.</p>
<p>Once the <code>clearTokens</code> function has finished its execution, the <code>logout</code> function sends the response with the HTTP status code of 204 (which means "No Content") back to the client.</p>
<p><strong>Refresh Access Token Controller</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);
<span class="hljs-keyword">const</span> createError = <span class="hljs-built_in">require</span>(<span class="hljs-string">"http-errors"</span>);
<span class="hljs-keyword">const</span> ms = <span class="hljs-built_in">require</span>(<span class="hljs-string">'ms'</span>);

<span class="hljs-keyword">const</span> { clearTokens, generateJWT } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../utils/auth"</span>);
<span class="hljs-keyword">const</span> { users, tokens } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../data/data"</span>);

<span class="hljs-keyword">const</span> signUp = <span class="hljs-keyword">async</span> (req, res, next) =&gt; { .... };

<span class="hljs-keyword">const</span> login = <span class="hljs-keyword">async</span> (req, res, next) =&gt; { .... };

<span class="hljs-keyword">const</span> logout = <span class="hljs-keyword">async</span> (req, res, next) =&gt; { .... };

<span class="hljs-keyword">const</span> refreshAccessToken = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
  <span class="hljs-keyword">const</span> { REFRESH_TOKEN_SECRET, ACCESS_TOKEN_SECRET, ACCESS_TOKEN_LIFE } = process.env;

  <span class="hljs-keyword">const</span> { signedCookies } = req;
  <span class="hljs-keyword">const</span> { refreshToken } = signedCookies;
  <span class="hljs-keyword">if</span> (!refreshToken) {
    <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">204</span>);
  }
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> refreshTokenInDB = tokens.find(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> token.refreshToken == refreshToken)?.refreshToken;

    <span class="hljs-keyword">if</span> (!refreshTokenInDB) {
      <span class="hljs-keyword">await</span> clearTokens(req, res, next);
      <span class="hljs-keyword">const</span> error = createError.Unauthorized();
      <span class="hljs-keyword">throw</span> error;
    }

    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> decodedToken = jwt.verify(refreshToken, REFRESH_TOKEN_SECRET);
      <span class="hljs-keyword">const</span> { userId } = decodedToken;
      <span class="hljs-keyword">const</span> user = users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> user.id == userId);

      <span class="hljs-keyword">if</span> (!user) {
        <span class="hljs-keyword">await</span> clearTokens(req, res);
        <span class="hljs-keyword">const</span> error = createError(<span class="hljs-string">"Invalid credentials"</span>, <span class="hljs-number">401</span>);
        <span class="hljs-keyword">throw</span> error;
      }

      <span class="hljs-keyword">const</span> accessToken = generateJWT(
        user.id,
        ACCESS_TOKEN_SECRET,
        ACCESS_TOKEN_LIFE
      );
      <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).json({
        user,
        accessToken,
        <span class="hljs-attr">expiresAt</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-built_in">Date</span>.now() + ms(ACCESS_TOKEN_LIFE)),
      });
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-keyword">return</span> next(error);
    }
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">return</span> next(error);
  }
};

<span class="hljs-built_in">module</span>.exports = {
    signUp,
    login,
    logout,
    refreshAccessToken
};
</code></pre>
<p>This <code>refreshAccessToken</code> function is responsible for refreshing the access token of a user. The function first checks for a refresh token in the signed cookies of the request. If a refresh token is found, it checks if the token is valid by comparing it with the tokens stored in the <code>tokens</code> array.</p>
<p>If the token is invalid, it clears all tokens and throws an error with a 401 status code. If the token is valid, it decodes the refresh token to get the user ID, checks if the user is valid, generates a new access token, and returns it along with the user information and the expiration time. If there is an error in the process, the function passes the error to the next error-handling middleware function.</p>
<p><strong>Adding Users Controllers</strong></p>
<p>Add this code to the <code>users.js</code> file inside the <code>controllers</code> folder.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> createError = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http-errors'</span>);

<span class="hljs-keyword">const</span> { users } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../data/data'</span>);

<span class="hljs-keyword">const</span> getUsersList = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">const</span> usersListWithOutPassword = users.map(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> {password, ...userWithOutPassword} = user;
        <span class="hljs-keyword">return</span> {...userWithOutPassword};
    });

    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).json({
        <span class="hljs-attr">data</span>: usersListWithOutPassword
    })
};

<span class="hljs-keyword">const</span> getAuthenticatedUser = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> { userId } = req;

        <span class="hljs-keyword">const</span> authenticatedUser = users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> user.id == userId);

        <span class="hljs-keyword">if</span>(authenticatedUser) {
            <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).json({
                <span class="hljs-attr">data</span>: authenticatedUser
            })
        }

        <span class="hljs-keyword">const</span> error = createError.NotFound();
        <span class="hljs-keyword">throw</span> error;

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

};

<span class="hljs-keyword">const</span> getUserById = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> { id } = req.params;

        <span class="hljs-keyword">const</span> user = users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> user.id == id);

        <span class="hljs-keyword">if</span> (user) {
            <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).json({
                <span class="hljs-attr">data</span>: user
            })
        }

        <span class="hljs-keyword">const</span> error = createError.NotFound();
        <span class="hljs-keyword">throw</span> error;
    } <span class="hljs-keyword">catch</span>(error) {
        <span class="hljs-keyword">return</span> next(error);
    }
};

<span class="hljs-built_in">module</span>.exports = {
    getUsersList,
    getAuthenticatedUser,
    getUserById
}
</code></pre>
<ol>
<li><p><code>getUsersList</code>: This function returns a list of all users.</p>
</li>
<li><p><code>getAuthenticatedUser</code>: This function returns the currently authenticated user based on their <code>userId</code>.</p>
</li>
<li><p><code>getUserById</code>: This function returns a user by their ID.</p>
</li>
</ol>
<p><strong>Adding Auth Middlewares</strong></p>
<p>Add this code to the <code>auth.js</code> file inside the <code>middlewares</code> folder.</p>
<p><code>generateAuthTokens</code> <strong>middleware</strong></p>
<p>This middleware is used to generate access and refresh tokens once a user successfully signs up or logs into our application.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);
<span class="hljs-keyword">const</span> createError = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http-errors'</span>);
<span class="hljs-keyword">const</span> ms = <span class="hljs-built_in">require</span>(<span class="hljs-string">'ms'</span>);

<span class="hljs-keyword">const</span> { generateJWT } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../utils/auth'</span>);

<span class="hljs-keyword">const</span> { ACCESS_TOKEN_LIFE, REFRESH_TOKEN_LIFE, ACCESS_TOKEN_SECRET, REFRESH_TOKEN_SECRET, NODE_ENV } = process.env;

<span class="hljs-keyword">const</span> dev = NODE_ENV === <span class="hljs-string">'development'</span>;

<span class="hljs-keyword">const</span> { users, tokens } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../data/data'</span>);

<span class="hljs-keyword">const</span> generateAuthTokens = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> user = users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> user.id === req.userId);

        <span class="hljs-keyword">const</span> refreshToken = generateJWT(
            req.userId,
            REFRESH_TOKEN_SECRET,
            REFRESH_TOKEN_LIFE
        );

        <span class="hljs-keyword">const</span> accessToken = generateJWT(
            req.userId, 
            ACCESS_TOKEN_SECRET, 
            ACCESS_TOKEN_LIFE
        );

        <span class="hljs-keyword">const</span> token = {
            refreshToken,
            <span class="hljs-attr">userId</span>: req.userId,
            <span class="hljs-attr">expirationTime</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-built_in">Date</span>.now() + ms(REFRESH_TOKEN_LIFE)).getTime(),
        };

        tokens.push(token);

        res.cookie(<span class="hljs-string">"refreshToken"</span>, refreshToken, {
            <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>,
            <span class="hljs-attr">secure</span>: !dev,
            <span class="hljs-attr">signed</span>: <span class="hljs-literal">true</span>,
            <span class="hljs-attr">expires</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-built_in">Date</span>.now() + ms(REFRESH_TOKEN_LIFE)),
        });

        <span class="hljs-keyword">const</span> expiresAt = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(<span class="hljs-built_in">Date</span>.now() + ms(ACCESS_TOKEN_LIFE));

        <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).json({
            user,
            <span class="hljs-attr">token</span>: accessToken,
            expiresAt,
        });
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-keyword">return</span> next(error);
    }
};

<span class="hljs-built_in">module</span>.exports = {
    generateAuthTokens
}
</code></pre>
<p>The refresh and access tokens are generated by calling the <code>generateJWT</code> function with the authenticated user's ID, token secret, and the token expiration time.</p>
<p>Here I am sending the access token as part of the response body along with its expiration time and the authenticated user's object, and sending the refresh token as an <code>httpOnly</code> cookie. I am also saving the refresh token in the database (<code>tokens</code> array here) to invalidate the user's session from the backend.</p>
<p><strong>Note:—</strong> I am sending the refresh token as an <code>httpOnly</code> cookie to prevent it from being read using JavaScript, and setting the <code>secure</code> attribute to false in development mode and true in production to only send cookies using HTTPS in production.</p>
<p><code>isAuthenticated</code> <strong>Middleware</strong></p>
<p>This middleware is used to check if the user is authenticated to access the protected routes.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);
<span class="hljs-keyword">const</span> createError = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http-errors'</span>);
<span class="hljs-keyword">const</span> ms = <span class="hljs-built_in">require</span>(<span class="hljs-string">'ms'</span>);

<span class="hljs-keyword">const</span> { generateJWT } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../utils/auth'</span>);

<span class="hljs-keyword">const</span> { ACCESS_TOKEN_LIFE, REFRESH_TOKEN_LIFE, ACCESS_TOKEN_SECRET, REFRESH_TOKEN_SECRET, NODE_ENV } = process.env;

<span class="hljs-keyword">const</span> dev = NODE_ENV === <span class="hljs-string">'development'</span>;

<span class="hljs-keyword">const</span> { users, tokens } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../data/data'</span>);

<span class="hljs-keyword">const</span> generateAuthTokens = <span class="hljs-keyword">async</span> (req, res, next) =&gt; { ... };

<span class="hljs-keyword">const</span> isAuthenticated = <span class="hljs-keyword">async</span> (req, res, next) =&gt; {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> authToken = req.get(<span class="hljs-string">'Authorization'</span>);
        <span class="hljs-keyword">const</span> accessToken = authToken?.split(<span class="hljs-string">'Bearer '</span>)[<span class="hljs-number">1</span>];
        <span class="hljs-keyword">if</span> (!accessToken) {
            <span class="hljs-keyword">const</span> error = createError.Unauthorized();
            <span class="hljs-keyword">throw</span> error;
        }

        <span class="hljs-keyword">const</span> { signedCookies = {} } = req;

        <span class="hljs-keyword">const</span> { refreshToken } = signedCookies;
        <span class="hljs-keyword">if</span> (!refreshToken) {
            <span class="hljs-keyword">const</span> error = createError.Unauthorized();
            <span class="hljs-keyword">throw</span> error;
        }

        <span class="hljs-keyword">let</span> refreshTokenInDB = tokens.find(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> token.refreshToken === refreshToken);

        <span class="hljs-keyword">if</span> (!refreshTokenInDB) {
            <span class="hljs-keyword">const</span> error = createError.Unauthorized();
            <span class="hljs-keyword">throw</span> error;
        }

        refreshTokenInDB = refreshTokenInDB.refreshToken;

        <span class="hljs-keyword">let</span> decodedToken;
        <span class="hljs-keyword">try</span> {
            decodedToken = jwt.verify(accessToken, ACCESS_TOKEN_SECRET);
        } <span class="hljs-keyword">catch</span> (err) {
            <span class="hljs-keyword">const</span> error = createError.Unauthorized();
            <span class="hljs-keyword">return</span> next(error);
        }

        <span class="hljs-keyword">const</span> { userId } = decodedToken;

        <span class="hljs-keyword">const</span> user = users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> user.id == userId);
        <span class="hljs-keyword">if</span> (!user) {
            <span class="hljs-keyword">const</span> error = createError.Unauthorized();
            <span class="hljs-keyword">throw</span> error;
        }

        req.userId = user.id;
        <span class="hljs-keyword">return</span> next();
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-keyword">return</span> next(error);
    }
};

<span class="hljs-built_in">module</span>.exports = {
    generateAuthTokens,
    isAuthenticated
}
</code></pre>
<p>This middleware function checks whether the incoming request is authenticated or not. It does this by first checking if the request has an access token in the authorization header. If it doesn't, the function throws an error indicating that the request is unauthorized.</p>
<p>If the request has an access token, the middleware function checks for the presence of a refresh token in a signed cookie. If there is no refresh token, the function throws an error indicating that the request is unauthorized.</p>
<p>If the request has both an access token and a refresh token, the middleware function checks whether the refresh token is present in the database. If it is not, the function throws an error indicating that the request is unauthorized.</p>
<p>If the refresh token is present in the database, the middleware function attempts to decode the access token using the access token secret. If the decoding fails, the function throws an error indicating that the request is unauthorized.</p>
<p>If the decoding succeeds, the middleware function retrieves the user ID from the decoded token, and checks if there is a user in the database with that ID. If there is no user, the function throws an error indicating that the request is unauthorized.</p>
<p>If the user is found, the middleware function sets the <code>userId</code> property of the request object to the user's ID and calls the <code>next()</code> function to pass control to the next middleware function in the chain.</p>
<p><strong>Adding Utility Functions</strong></p>
<p>Add this code inside the <code>auth.js</code> file inside the <code>utils</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);

<span class="hljs-keyword">const</span> { tokens } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'../data/data'</span>);

<span class="hljs-keyword">const</span> dev = process.env.NODE_ENV === <span class="hljs-string">'development'</span>;

<span class="hljs-keyword">const</span> generateJWT = <span class="hljs-function">(<span class="hljs-params">userId, secret, expirationTime</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> jwt.sign(
        {
            userId,
        },
        secret,
        { <span class="hljs-attr">expiresIn</span>: expirationTime }
    );
}
<span class="hljs-keyword">const</span> clearTokens = <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">const</span> { signedCookies = {} } = req;
    <span class="hljs-keyword">const</span> { refreshToken } = signedCookies;
    <span class="hljs-keyword">if</span> (refreshToken) {
        <span class="hljs-keyword">const</span> index = tokens.findIndex(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> token.refreshToken === refreshToken);
        <span class="hljs-keyword">if</span>(index) {
            tokens.splice(index, <span class="hljs-number">1</span>);
        }
    }
    res.clearCookie(<span class="hljs-string">'refreshToken'</span>, {
        <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">secure</span>: !dev,
        <span class="hljs-attr">signed</span>: <span class="hljs-literal">true</span>,
    });
};

<span class="hljs-built_in">module</span>.exports = {
    generateJWT,
    clearTokens
};
</code></pre>
<ol>
<li><p><code>generateJWT</code>: This function is used to generate the access and refresh token using the <code>jsonwebtoken</code> library.</p>
</li>
<li><p><code>clearTokens</code>: This function is used clear the refresh token from the database and the cookie when a user logs out from the application.</p>
</li>
</ol>
<h3 id="heading-creating-react-application">Creating React Application</h3>
<p>Run the following commands to initialize the React application and install the required dependencies.</p>
<pre><code class="lang-javascript">cd refresh-token-auth-app
npx create-react-app client
</code></pre>
<pre><code class="lang-javascript">cd client
npm install axios react-router-dom react-hook-form
npm install --save-dev sass
</code></pre>
<p><strong>Folder Structure</strong></p>
<p>Before we start writing any code, let's create the folder structure required for the front-end application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685626728894/8256d0f2-3a28-4cd2-9328-83818d3e8f0d.png" alt class="image--center mx-auto" /></p>
<p>You can create the above directories with these commands.</p>
<pre><code class="lang-javascript">cd client/src
mkdir components contexts utils
</code></pre>
<p><strong>(Optional) Adding fonts and styles</strong></p>
<ul>
<li>Add this font to the <code>head</code> section of the <code>index.html</code> file under the <code>public</code> directory.</li>
</ul>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Urbanist:wght@300;400;500;700&amp;display=swap"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> /&gt;</span>
</code></pre>
<ul>
<li>Replace the <code>CSS</code> code inside the <code>index.css</code> with the code below:</li>
</ul>
<pre><code class="lang-css">*<span class="hljs-selector-pseudo">::before</span>,
*,
*<span class="hljs-selector-pseudo">::after</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">box-sizing</span>: border-box;
  <span class="hljs-attribute">font-family</span>: inherit;
}

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Urbanist'</span>, sans-serif;
  <span class="hljs-attribute">-webkit-font-smoothing</span>: antialiased;
  <span class="hljs-attribute">-moz-osx-font-smoothing</span>: grayscale;
}
</code></pre>
<ul>
<li>And finally, remove the code inside the <code>App.css</code> file or delete the <code>App.css</code> as we won't need this file in this tutorial.</li>
</ul>
<p><strong>Proxying API Requests</strong></p>
<p>Add this line of code to the <code>package.json</code> file if you want to write requests like <code>axios.post('/api/auth/sign-up')</code> instead of <code>axios.post('http://localhost:5000/api/auth/sign-up')</code></p>
<pre><code class="lang-javascript">  <span class="hljs-string">"proxy"</span>: <span class="hljs-string">"http://localhost:5000"</span>
</code></pre>
<p><strong>Signup Component</strong></p>
<p>Let's start by creating the signup component, which allows users to sign up for our application by filling out the signup form.</p>
<p><strong>Note:—</strong> We will use CSS modules to style our React application. So for each component, we will also create a CSS or SCSS file for that component.</p>
<p><code>Signup.js</code></p>
<p>Create a new folder <code>Signup</code> under the <code>components</code> directory and create a new file <code>Signup.js</code> under that new folder.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Signup.module.scss"</span>;

<span class="hljs-keyword">const</span> Signup = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> {
    handleSubmit,
    register,
    <span class="hljs-attr">formState</span>: { errors, touchedFields },
  } = useForm({
    <span class="hljs-attr">defaultValues</span>: {
      <span class="hljs-attr">name</span>: <span class="hljs-string">""</span>,
      <span class="hljs-attr">username</span>: <span class="hljs-string">""</span>,
      <span class="hljs-attr">email</span>: <span class="hljs-string">""</span>,
      <span class="hljs-attr">password</span>: <span class="hljs-string">""</span>,
      <span class="hljs-attr">confirmPassword</span>: <span class="hljs-string">""</span>,
    },
    <span class="hljs-attr">mode</span>: <span class="hljs-string">"onChange"</span>,
  });

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-keyword">async</span> (values) =&gt; {};

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formWrapper}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.form}</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(onSubmit)}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formTitle}</span>&gt;</span>Create New Account<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Name"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">name</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Name</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
                <span class="hljs-attr">minLength:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">2</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Name</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">less</span> <span class="hljs-attr">than</span> <span class="hljs-attr">2</span> <span class="hljs-attr">characters</span>" },
                <span class="hljs-attr">maxLength:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">30</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Name</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">more</span> <span class="hljs-attr">than</span> <span class="hljs-attr">30</span> <span class="hljs-attr">characters</span>" },
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.name &amp;&amp; errors.name?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"username"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Username"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">username</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Username</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
                <span class="hljs-attr">minLength:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">2</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Username</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">less</span> <span class="hljs-attr">than</span> <span class="hljs-attr">2</span> <span class="hljs-attr">characters</span>" }
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.username &amp;&amp; errors.username?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">autoComplete</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">email</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Email</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
                <span class="hljs-attr">pattern:</span> { <span class="hljs-attr">value:</span> /^[<span class="hljs-attr">a-zA-Z0-9._</span>%+<span class="hljs-attr">-</span>]+@[<span class="hljs-attr">a-zA-Z0-9.-</span>]+\<span class="hljs-attr">.</span>[<span class="hljs-attr">a-zA-Z</span>]{<span class="hljs-attr">2</span>,}$/, <span class="hljs-attr">message:</span> '<span class="hljs-attr">Please</span> <span class="hljs-attr">enter</span> <span class="hljs-attr">a</span> <span class="hljs-attr">valid</span> <span class="hljs-attr">email</span>'}
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.email &amp;&amp; errors.email?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">autoComplete</span>=<span class="hljs-string">"new-password"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Password"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">password</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Password</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
                <span class="hljs-attr">minLength:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">6</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Password</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">less</span> <span class="hljs-attr">than</span> <span class="hljs-attr">6</span> <span class="hljs-attr">characters</span>"},
                <span class="hljs-attr">maxLength:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">30</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Password</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">more</span> <span class="hljs-attr">than</span> <span class="hljs-attr">30</span> <span class="hljs-attr">characters</span>"}
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.password &amp;&amp; errors.password?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"confirmPassword"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"confirmPassword"</span>
              <span class="hljs-attr">autoComplete</span>=<span class="hljs-string">"new-password"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Confirm Password"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">confirmPassword</span>", {
                <span class="hljs-attr">required:</span> {
                  <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>,
                  <span class="hljs-attr">message:</span> "<span class="hljs-attr">confirmPassword</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>",
                },
                <span class="hljs-attr">validate:</span> (<span class="hljs-attr">value</span>, <span class="hljs-attr">formValues</span>) =&gt;</span> {
                  if(value !== formValues.password) {
                    return 'Confirm password does not match the password';
                  }
                  return true;
                }
              })}
            /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
                {touchedFields.confirmPassword &amp;&amp;
                  errors.confirmPassword?.message}
              <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.submitButton}</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Sign Up<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.text}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
              Already have an account?
            <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.link}</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/login"</span>&gt;</span>Login<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Signup;
</code></pre>
<p>It's just a simple sign-up form that contains name, username, email, password, and confirm password input fields using which a user can sign up for our application.</p>
<p><strong>Note:—</strong> Here I am using the React Hook Form library to manage the sign-up form. You can use the HTML form validation to validate the form if you don't want to use any external library.</p>
<p><code>Signup.module.scss</code></p>
<p>Add this code inside the <code>Signup.module.scss</code> under the <code>Signup</code> folder to style the sign-up form.</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">background-color</span>: rgb(<span class="hljs-number">0</span> <span class="hljs-number">128</span> <span class="hljs-number">128</span> / <span class="hljs-number">10%</span>);
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">40px</span> <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
}

<span class="hljs-selector-class">.formWrapper</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">box-sizing</span>: border-box;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.form</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span> <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">500px</span>;
  <span class="hljs-attribute">background</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">2px</span> <span class="hljs-number">2px</span> <span class="hljs-number">7px</span> <span class="hljs-number">2px</span> rgb(<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> / <span class="hljs-number">20%</span>);
  <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">10px</span>;

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  }
}

<span class="hljs-selector-class">.formTitle</span> {
  <span class="hljs-attribute">color</span>: teal;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">300</span>;
  <span class="hljs-attribute">text-align</span>: left;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">30px</span>;

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">22px</span>;
  }
}

<span class="hljs-selector-class">.formGroup</span> {
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">10px</span> <span class="hljs-number">0</span>;
}

<span class="hljs-selector-class">.input</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">11px</span> <span class="hljs-number">12px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">outline</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#d4d5d9</span>;
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#282c3f</span>;
  caret-<span class="hljs-attribute">color</span>: teal;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">500</span>;

  &amp;<span class="hljs-selector-pseudo">:focus</span> {
    <span class="hljs-attribute">outline</span>: <span class="hljs-number">1px</span> solid teal;
  }

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  }

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  }
}

<span class="hljs-selector-class">.submitButton</span> {
  <span class="hljs-attribute">background</span>: teal;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid transparent;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span> <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  <span class="hljs-attribute">text-transform</span>: uppercase;
  <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-class">.validationError</span> {
  <span class="hljs-attribute">color</span>: red;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.text</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#1b2839</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">500</span>;

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  }

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  }
}

<span class="hljs-selector-class">.link</span> {
  <span class="hljs-attribute">color</span>: teal;
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">5px</span>;
}
</code></pre>
<p><strong>Adding the Sign-up Route</strong></p>
<p>Replace the code inside the <code>App.js</code> file with the code below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createBrowserRouter, RouterProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

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

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> router = createBrowserRouter([
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
    },
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"sign-up"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Signup</span> /&gt;</span></span>,
    },
  ]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">RouterProvider</span> <span class="hljs-attr">router</span>=<span class="hljs-string">{router}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>You can now visit the sign-up page by going to <code>http://localhost:3000/sign-up</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684595656887/8f68323f-d621-4239-b6c3-3462eda09642.png" alt="sign-up page" class="image--center mx-auto" /></p>
<p><strong>Making the Form Work</strong></p>
<p>So we have made the sign-up form but the users can't actually sign up through it. Let's connect the form with the backend, which allows users to sign up if they haven't already.</p>
<p><strong>Saving Authentication State Using Context API</strong></p>
<p>Before we connect our form with the backend, let's create a context to store the currently authenticated user.</p>
<p><code>auth-context.js</code></p>
<p>Add this file under the <code>src/contexts</code> directory and add the following code to that file.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> PropTypes <span class="hljs-keyword">from</span> <span class="hljs-string">'prop-types'</span>;

<span class="hljs-keyword">import</span> { STATUS } <span class="hljs-keyword">from</span> <span class="hljs-string">'../utils/utils'</span>;

<span class="hljs-keyword">const</span> initialState = {
  <span class="hljs-attr">user</span>: {},
  <span class="hljs-attr">token</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">expiresAt</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">isAuthenticated</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">status</span>: STATUS.PENDING,
};

<span class="hljs-keyword">const</span> AuthContext = React.createContext({
  ...initialState,
  <span class="hljs-attr">login</span>: <span class="hljs-function">(<span class="hljs-params">user = {}, token = <span class="hljs-string">''</span>, expiresAt = <span class="hljs-string">''</span></span>) =&gt;</span> {},
  <span class="hljs-attr">logout</span>: <span class="hljs-function">() =&gt;</span> {},
  <span class="hljs-attr">updateUser</span>: <span class="hljs-function">() =&gt;</span> {},
  <span class="hljs-attr">setAuthenticationStatus</span>: <span class="hljs-function">() =&gt;</span> {},
});

<span class="hljs-keyword">const</span> authReducer = <span class="hljs-function">(<span class="hljs-params">state, action</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (action.type) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">'login'</span>: {
      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">user</span>: action.payload.user,
        <span class="hljs-attr">token</span>: action.payload.token,
        <span class="hljs-attr">expiresAt</span>: action.payload.expiresAt,
        <span class="hljs-attr">isAuthenticated</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">verifyingToken</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">status</span>: STATUS.SUCCEEDED,
      };
    }
    <span class="hljs-keyword">case</span> <span class="hljs-string">'logout'</span>: {
      <span class="hljs-keyword">return</span> {
        ...initialState,
        <span class="hljs-attr">status</span>: STATUS.IDLE,
      };
    }
    <span class="hljs-keyword">case</span> <span class="hljs-string">'updateUser'</span>: {
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">user</span>: action.payload.user,
      };
    }
    <span class="hljs-keyword">case</span> <span class="hljs-string">'status'</span>: {
      <span class="hljs-keyword">return</span> {
        ...state,
        <span class="hljs-attr">status</span>: action.payload.status,
      };
    }
    <span class="hljs-attr">default</span>: {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Unhandled action type: <span class="hljs-subst">${action.type}</span>`</span>);
    }
  }
};

<span class="hljs-keyword">const</span> AuthProvider = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [state, dispatch] = React.useReducer(authReducer, initialState);

  <span class="hljs-keyword">const</span> login = React.useCallback(<span class="hljs-function">(<span class="hljs-params">user, token, expiresAt</span>) =&gt;</span> {
    dispatch({
      <span class="hljs-attr">type</span>: <span class="hljs-string">'login'</span>,
      <span class="hljs-attr">payload</span>: {
        user,
        token,
        expiresAt,
      },
    });
  }, []);

  <span class="hljs-keyword">const</span> logout = React.useCallback(<span class="hljs-function">() =&gt;</span> {
    dispatch({
      <span class="hljs-attr">type</span>: <span class="hljs-string">'logout'</span>,
    });
  }, []);

  <span class="hljs-keyword">const</span> updateUser = React.useCallback(<span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> {
    dispatch({
      <span class="hljs-attr">type</span>: <span class="hljs-string">'updateUser'</span>,
      <span class="hljs-attr">payload</span>: {
        user,
      },
    });
  }, []);

  <span class="hljs-keyword">const</span> setAuthenticationStatus = React.useCallback(<span class="hljs-function">(<span class="hljs-params">status</span>) =&gt;</span> {
    dispatch({
      <span class="hljs-attr">type</span>: <span class="hljs-string">'status'</span>,
      <span class="hljs-attr">payload</span>: {
        status,
      },
    });
  }, []);

  <span class="hljs-keyword">const</span> value = React.useMemo(
    <span class="hljs-function">() =&gt;</span> ({ ...state, login, logout, updateUser, setAuthenticationStatus }),
    [state, setAuthenticationStatus, login, logout, updateUser]
  );

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AuthContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{value}</span>&gt;</span>{children}<span class="hljs-tag">&lt;/<span class="hljs-name">AuthContext.Provider</span>&gt;</span></span>;
};

<span class="hljs-keyword">const</span> useAuth = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> context = React.useContext(AuthContext);

  <span class="hljs-keyword">if</span> (context === <span class="hljs-literal">undefined</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'useAuth must be used within a AuthProvider'</span>);
  }

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

AuthProvider.propTypes = {
  <span class="hljs-attr">children</span>: PropTypes.element.isRequired,
};

<span class="hljs-keyword">export</span> { AuthProvider, useAuth };
</code></pre>
<p>In this code, I am using a custom hook <code>useAuth</code> which returns the current context value created using the <code>AuthContext</code> which contains the authentication state along with the functions used to log in, log out, and update the authentication status.</p>
<p>I am also defining a component <code>AuthProvider</code> that returns the context provider <code>AuthContext.Provider</code>. The <code>AuthProvider</code> component uses the <code>useReducer</code> hook to update the authentication state whenever a user logs in or logs out of the application.</p>
<p>The state returned by the <code>useReducer</code> is then passed as the value (along with functions like <code>login</code> and <code>logout</code> which updates the auth state using the dispatch method returned by the <code>useReducer</code> hook) to the <code>AuthContext.Provider</code>. The <code>AuthContext.Provider</code> also contains components passed to the <code>AuthProvider</code> component as children.</p>
<p><code>utils.js</code></p>
<p>Add this code inside the <code>src/utils/utils.js</code> file.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> STATUS = <span class="hljs-built_in">Object</span>.freeze({
  <span class="hljs-attr">IDLE</span>: <span class="hljs-string">'idle'</span>,
  <span class="hljs-attr">PENDING</span>: <span class="hljs-string">'pending'</span>,
  <span class="hljs-attr">SUCCEEDED</span>: <span class="hljs-string">'succeeded'</span>,
  <span class="hljs-attr">FAILED</span>: <span class="hljs-string">'failed'</span>,
});

<span class="hljs-keyword">export</span> {
    STATUS
}
</code></pre>
<p>This code defines an object which is used to represent the status of an HTTP request whether it is pending, failed, or succeeded.</p>
<p><strong>Using the AuthProvider</strong></p>
<p>Replace the code inside the <code>src/index.js</code> file with the code below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> reportWebVitals <span class="hljs-keyword">from</span> <span class="hljs-string">'./reportWebVitals'</span>;
<span class="hljs-keyword">import</span> { AuthProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'./contexts/auth-context'</span>;

<span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>));
root.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">AuthProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">AuthProvider</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);

<span class="hljs-comment">// If you want to start measuring performance in your app, pass a function</span>
<span class="hljs-comment">// to log results (for example: reportWebVitals(console.log))</span>
<span class="hljs-comment">// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals</span>
reportWebVitals();
</code></pre>
<p>Using this code, every component nested deep inside the <code>&lt;App /&gt;</code> component can now access and update the authentication state using the <code>useAuth</code> custom hook.</p>
<p><strong>Connecting the form with the backend</strong></p>
<p>Update the code inside the <code>Signup.js</code> file with the code below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Link, useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-keyword">import</span> { useAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../contexts/auth-context"</span>;
<span class="hljs-keyword">import</span> { STATUS } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../utils/utils"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Signup.module.scss"</span>;

<span class="hljs-keyword">const</span> Signup = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Existing code</span>
  <span class="hljs-keyword">const</span> {
    handleSubmit,
    register,
    <span class="hljs-attr">formState</span>: { errors, touchedFields },
  } = useForm({
    <span class="hljs-attr">defaultValues</span>: {
      <span class="hljs-attr">name</span>: <span class="hljs-string">""</span>,
      <span class="hljs-attr">username</span>: <span class="hljs-string">""</span>,
      <span class="hljs-attr">email</span>: <span class="hljs-string">""</span>,
      <span class="hljs-attr">password</span>: <span class="hljs-string">""</span>,
      <span class="hljs-attr">confirmPassword</span>: <span class="hljs-string">""</span>,
    },
    <span class="hljs-attr">mode</span>: <span class="hljs-string">"onChange"</span>,
  });

  <span class="hljs-comment">// New code</span>
  <span class="hljs-keyword">const</span> navigate = useNavigate();

  <span class="hljs-keyword">const</span> { login, setAuthenticationStatus } = useAuth();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-keyword">async</span> (values) =&gt; {
    <span class="hljs-keyword">const</span> newUser = {
      <span class="hljs-attr">name</span>: values.name,
      <span class="hljs-attr">username</span>: values.username,
      <span class="hljs-attr">email</span>: values.email,
      <span class="hljs-attr">password</span>: values.password,
      <span class="hljs-attr">confirmPassword</span>: values.confirmPassword,
    };

    <span class="hljs-keyword">try</span> {
      setAuthenticationStatus(STATUS.PENDING);
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.post(<span class="hljs-string">"/api/auth/sign-up"</span>, newUser);
      setAuthenticationStatus(STATUS.SUCCEEDED);
      <span class="hljs-keyword">const</span> { user, token, expiresAt } = response.data;
      login(user, token, expiresAt);
      navigate(<span class="hljs-string">"/"</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      alert(error.response.data.error.message);
      setAuthenticationStatus(STATUS.FAILED);
    }
  };

  <span class="hljs-comment">// Existing code</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formWrapper}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.form}</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(onSubmit)}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formTitle}</span>&gt;</span>Create New Account<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Name"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">name</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Name</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
                <span class="hljs-attr">minLength:</span> {
                  <span class="hljs-attr">value:</span> <span class="hljs-attr">2</span>,
                  <span class="hljs-attr">message:</span> "<span class="hljs-attr">Name</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">less</span> <span class="hljs-attr">than</span> <span class="hljs-attr">2</span> <span class="hljs-attr">characters</span>",
                },
                <span class="hljs-attr">maxLength:</span> {
                  <span class="hljs-attr">value:</span> <span class="hljs-attr">30</span>,
                  <span class="hljs-attr">message:</span> "<span class="hljs-attr">Name</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">more</span> <span class="hljs-attr">than</span> <span class="hljs-attr">30</span> <span class="hljs-attr">characters</span>",
                },
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.name &amp;&amp; errors.name?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"username"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Username"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">username</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Username</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
                <span class="hljs-attr">minLength:</span> {
                  <span class="hljs-attr">value:</span> <span class="hljs-attr">2</span>,
                  <span class="hljs-attr">message:</span> "<span class="hljs-attr">Username</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">less</span> <span class="hljs-attr">than</span> <span class="hljs-attr">2</span> <span class="hljs-attr">characters</span>",
                },
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.username &amp;&amp; errors.username?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">autoComplete</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Email"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">email</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Email</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
                <span class="hljs-attr">pattern:</span> {
                  <span class="hljs-attr">value:</span> /^[<span class="hljs-attr">a-zA-Z0-9._</span>%+<span class="hljs-attr">-</span>]+@[<span class="hljs-attr">a-zA-Z0-9.-</span>]+\<span class="hljs-attr">.</span>[<span class="hljs-attr">a-zA-Z</span>]{<span class="hljs-attr">2</span>,}$/,
                  <span class="hljs-attr">message:</span> "<span class="hljs-attr">Please</span> <span class="hljs-attr">enter</span> <span class="hljs-attr">a</span> <span class="hljs-attr">valid</span> <span class="hljs-attr">email</span>",
                },
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.email &amp;&amp; errors.email?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">autoComplete</span>=<span class="hljs-string">"new-password"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Password"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">password</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Password</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
                <span class="hljs-attr">minLength:</span> {
                  <span class="hljs-attr">value:</span> <span class="hljs-attr">6</span>,
                  <span class="hljs-attr">message:</span> "<span class="hljs-attr">Password</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">less</span> <span class="hljs-attr">than</span> <span class="hljs-attr">6</span> <span class="hljs-attr">characters</span>",
                },
                <span class="hljs-attr">maxLength:</span> {
                  <span class="hljs-attr">value:</span> <span class="hljs-attr">30</span>,
                  <span class="hljs-attr">message:</span> "<span class="hljs-attr">Password</span> <span class="hljs-attr">cannot</span> <span class="hljs-attr">be</span> <span class="hljs-attr">more</span> <span class="hljs-attr">than</span> <span class="hljs-attr">30</span> <span class="hljs-attr">characters</span>",
                },
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.password &amp;&amp; errors.password?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"confirmPassword"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"confirmPassword"</span>
              <span class="hljs-attr">autoComplete</span>=<span class="hljs-string">"new-password"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Confirm Password"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">confirmPassword</span>", {
                <span class="hljs-attr">required:</span> {
                  <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>,
                  <span class="hljs-attr">message:</span> "<span class="hljs-attr">confirmPassword</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>",
                },
                <span class="hljs-attr">validate:</span> (<span class="hljs-attr">value</span>, <span class="hljs-attr">formValues</span>) =&gt;</span> {
                  if (value !== formValues.password) {
                    return "Confirm password does not match the password";
                  }
                  return true;
                },
              })}
            /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>
                {touchedFields.confirmPassword &amp;&amp;
                  errors.confirmPassword?.message}
              <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.submitButton}</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>
              Sign Up
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.text}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Already have an account?<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.link}</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/login"</span>&gt;</span>
              Login
            <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Signup;
</code></pre>
<p>The <code>onSubmit</code> method is called when the user submits the signup form. Inside the function, a new object called <code>newUser</code> is created with its properties set to form values. Inside the <code>try...catch</code> block, we call the signup API with the <code>newUser</code> object as the request body.</p>
<p>If the request is successful, we extract the user, token, and the token expiry time from the response and call the login function from the useAuth hook. This function updates the authentication state with the new user and token, and redirects the user to the home page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684768614720/bc1b1bca-8aff-47cd-86be-488733403152.png" alt="sign up API response" class="image--center mx-auto" /></p>
<p><strong>Login Component</strong></p>
<p><code>Login.js</code></p>
<p>Add this code inside the <code>Login.js</code> file under the <code>src/components/Login</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Link, useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> { useForm } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-hook-form"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-keyword">import</span> { useAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../contexts/auth-context"</span>;
<span class="hljs-keyword">import</span> { STATUS } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../utils/utils"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Login.module.scss"</span>;

<span class="hljs-keyword">const</span> Login = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> {
    handleSubmit,
    register,
    <span class="hljs-attr">formState</span>: { errors, touchedFields },
  } = useForm({
    <span class="hljs-attr">defaultValues</span>: {
      <span class="hljs-attr">username</span>: <span class="hljs-string">""</span>,
      <span class="hljs-attr">password</span>: <span class="hljs-string">""</span>,
    },
    <span class="hljs-attr">mode</span>: <span class="hljs-string">"onChange"</span>,
  });

  <span class="hljs-keyword">const</span> navigate = useNavigate();

  <span class="hljs-keyword">const</span> { login, setAuthenticationStatus } = useAuth();

  <span class="hljs-keyword">const</span> onSubmit = <span class="hljs-keyword">async</span> (values) =&gt; {
    <span class="hljs-keyword">const</span> user = {
      <span class="hljs-attr">username</span>: values.username,
      <span class="hljs-attr">password</span>: values.password,
    };

    <span class="hljs-keyword">try</span> {
      setAuthenticationStatus(STATUS.PENDING);
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.post(<span class="hljs-string">"/api/auth/login"</span>, user);
      setAuthenticationStatus(STATUS.SUCCEEDED);
      <span class="hljs-keyword">const</span> { <span class="hljs-attr">user</span>: userObj, token, expiresAt } = response.data;
      login(userObj, token, expiresAt);
      navigate(<span class="hljs-string">'/'</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      alert(error.response.data.error.message);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formWrapper}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.form}</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit(onSubmit)}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formTitle}</span>&gt;</span>Sign In<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"username"</span>
              <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Username or Email"</span>
              <span class="hljs-attr">required</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Username or Email"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">username</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">This</span> <span class="hljs-attr">field</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.name &amp;&amp; errors.name?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.input}</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>
              <span class="hljs-attr">required</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Password"</span>
              {<span class="hljs-attr">...register</span>("<span class="hljs-attr">password</span>", {
                <span class="hljs-attr">required:</span> { <span class="hljs-attr">value:</span> <span class="hljs-attr">true</span>, <span class="hljs-attr">message:</span> "<span class="hljs-attr">Password</span> <span class="hljs-attr">is</span> <span class="hljs-attr">required.</span>" },
              })}
            /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.validationError}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{touchedFields.password &amp;&amp; errors.password?.message}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.formGroup}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.submitButton}</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>
              Sign In
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.text}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>Don't have an account?<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.link}</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/sign-up"</span>&gt;</span>
              Sign Up
            <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Login;
</code></pre>
<p><code>Login.module.scss</code></p>
<p>Add this code inside the <code>Login.module.scss</code> file under the <code>src/components/Login</code> directory.</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">background-color</span>: rgb(<span class="hljs-number">0</span> <span class="hljs-number">128</span> <span class="hljs-number">128</span> / <span class="hljs-number">10%</span>);
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">40px</span> <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.formWrapper</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">500px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}

<span class="hljs-selector-class">.form</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">2px</span> <span class="hljs-number">2px</span> <span class="hljs-number">7px</span> <span class="hljs-number">2px</span> rgb(<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> / <span class="hljs-number">20%</span>);
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span> <span class="hljs-number">30px</span>;
}

<span class="hljs-selector-class">.formTitle</span> {
  <span class="hljs-attribute">color</span>: teal;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">300</span>;
  <span class="hljs-attribute">text-align</span>: left;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">30px</span>;
}

<span class="hljs-selector-class">.formGroup</span> {
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">10px</span> <span class="hljs-number">0</span>;
}

<span class="hljs-selector-class">.input</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">11px</span> <span class="hljs-number">12px</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">outline</span>: <span class="hljs-number">1px</span> solid <span class="hljs-number">#d4d5d9</span>;
  <span class="hljs-attribute">border</span>: none;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#282c3f</span>;
  caret-<span class="hljs-attribute">color</span>: teal;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">500</span>;

  &amp;<span class="hljs-selector-pseudo">:focus</span> {
    <span class="hljs-attribute">outline</span>: <span class="hljs-number">1px</span> solid teal;
  }

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  }

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  }
}

<span class="hljs-selector-class">.submitButton</span> {
  <span class="hljs-attribute">background</span>: teal;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid transparent;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span> <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  <span class="hljs-attribute">text-transform</span>: uppercase;
  <span class="hljs-attribute">cursor</span>: pointer;

  <span class="hljs-selector-pseudo">:disabled</span> {
    <span class="hljs-attribute">background-color</span>: grey;
  }
}

<span class="hljs-selector-class">.validationError</span> {
  <span class="hljs-attribute">color</span>: red;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.text</span> {
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#1b2839</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">500</span>;

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  }

  <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  }
}

<span class="hljs-selector-class">.link</span> {
  <span class="hljs-attribute">color</span>: teal;
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">5px</span>;
}
</code></pre>
<p><strong>Adding the Login Route</strong></p>
<p>Replace the code inside the <code>App.js</code> file with the code below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createBrowserRouter, RouterProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">import</span> Signup <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Signup/Signup"</span>;
<span class="hljs-keyword">import</span> Login <span class="hljs-keyword">from</span> <span class="hljs-string">'./components/Login/Login'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> router = createBrowserRouter([
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
    },
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"sign-up"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Signup</span> /&gt;</span></span>,
    },
    {
    <span class="hljs-attr">path</span>: <span class="hljs-string">"login"</span>,
    <span class="hljs-attr">element</span>: (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Login</span> /&gt;</span></span>
    ),
  },
  ]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">RouterProvider</span> <span class="hljs-attr">router</span>=<span class="hljs-string">{router}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>You can now visit the login page by going to <code>http://localhost:3000/login</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684769475592/eaf2a8de-eb04-4b91-ac01-76ac1ef914b1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1684774623745/b1c44bc3-fee1-4f6f-bc92-1ac08237b079.png" alt class="image--center mx-auto" /></p>
<p><strong>Adding Silent Authentication</strong></p>
<p>As we know the access token is only valid for 15 minutes, without silent authentication the user will have to log in again every time the token expires. To prevent users from getting logged out every time the token expires let's implement silent authentication:</p>
<p><strong>What is Silent Authentication?</strong></p>
<p>Silent Authentication is the process of refreshing the user's access token in the background before the token expires or when a user reloads the page. Because we are not storing access tokens in local storage (to prevent XSS attacks), we have to perform silent authentication on page reload as well.</p>
<p>Replace the code inside the <code>App.js</code> with the code below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useCallback, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { createBrowserRouter, RouterProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-keyword">import</span> Signup <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Signup/Signup"</span>;
<span class="hljs-keyword">import</span> Login <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Login/Login"</span>;

<span class="hljs-keyword">import</span> { useAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"./contexts/auth-context"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// New Code</span>
  <span class="hljs-keyword">const</span> { login, logout, isAuthenticated, expiresAt } = useAuth();

  <span class="hljs-keyword">const</span> refreshAccessToken = useCallback(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.post(
        <span class="hljs-string">"/api/auth/refresh"</span>,
        {},
        {
          <span class="hljs-attr">withCredentials</span>: <span class="hljs-literal">true</span>,
        }
      );

      <span class="hljs-keyword">const</span> { user, accessToken, expiresAt } = response.data;

      <span class="hljs-keyword">if</span> (response.status === <span class="hljs-number">204</span>) {
        logout();
      } <span class="hljs-keyword">else</span> {
        login(user, accessToken, expiresAt);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      logout();
    }
  }, [login, logout]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    refreshAccessToken();
  }, [refreshAccessToken]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">let</span> refreshAccessTokenTimerId;

    <span class="hljs-keyword">if</span> (isAuthenticated) {
      refreshAccessTokenTimerId = <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        refreshAccessToken();
      }, <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(expiresAt).getTime() - <span class="hljs-built_in">Date</span>.now() - <span class="hljs-number">10</span> * <span class="hljs-number">1000</span>);
    }

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">if</span> (isAuthenticated &amp;&amp; refreshAccessTokenTimerId) {
        <span class="hljs-built_in">clearTimeout</span>(refreshAccessTokenTimerId);
      }
    };
  }, [expiresAt, isAuthenticated, refreshAccessToken]);

  <span class="hljs-comment">// Existing code </span>
  <span class="hljs-keyword">const</span> router = createBrowserRouter([
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello World!!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>,
    },
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"sign-up"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Signup</span> /&gt;</span></span>,
    },
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"login"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Login</span> /&gt;</span></span>,
    },
  ]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">RouterProvider</span> <span class="hljs-attr">router</span>=<span class="hljs-string">{router}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p><strong>So What's happening here?</strong></p>
<p>Let's break down the code and explain its functionality step by step:</p>
<ul>
<li><p><code>refreshAccessToken</code> <strong>function</strong>: This function is responsible for refreshing the access token. It does so by making a <code>POST</code> request to <code>/api/auth/refresh</code> endpoint. Since the refresh token is stored as an <code>httpOnly</code> cookie, I am also setting the <code>withCredentials</code> option to true to automatically send the refresh token with the request. If the request is successful, we call the <code>login</code> function to update the access token stored in memory, otherwise, we log out the user if there's any error.</p>
</li>
<li><p><strong>Performing silent authentication on page reload:</strong> Since the access token is stored only in the memory and not in local storage or cookie, we have to perform silent authentication whenever the page reloads or the application is loaded for the first time. We do this by calling the <code>refreshAccessToken</code> function inside the first <code>useEffect</code> hook that only runs when the <code>App</code> component is mounted.</p>
</li>
<li><p><strong>Performing silent authentication before the access token expires:</strong> The second <code>useEffect</code> is responsible for performing silent authentication before the access token expires. This effect runs whenever a user signs up or logs in to the application or when the access token is refreshed. Inside this effect, we first check if the user is authenticated, if yes then we set a timer using the <code>setTimeout</code> which executes the <code>refreshAccessToken()</code> function 10 seconds before the access token expires. We clear the timer when the effect cleanup is run.</p>
</li>
</ul>
<p><strong>Adding additional routes and components</strong></p>
<p>A user is now able to sign up and log in to our application and can remain logged in as long as the refresh token is valid. Let's add some more routes and components which a user can only access when they are authenticated.</p>
<p><strong>Adding Home Component</strong></p>
<p>Add this code inside the <code>Home.js</code> file under the <code>src/components/Home</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../contexts/auth-context"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Home.module.scss"</span>;

<span class="hljs-keyword">const</span> Home = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { user } = useAuth();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.heading}</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.colorTeal}</span>&gt;</span>Welcome<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.colorBlack}</span>&gt;</span>{user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Home;
</code></pre>
<p>This is just a simple home page where we print the currently authenticated user's name on the screen.</p>
<p><code>Home.module.scss</code></p>
<p>Add this code inside the <code>Home.module.scss</code> file under the <code>src/components/Home</code> directory.</p>
<pre><code class="lang-javascript">.container {
    margin-top: <span class="hljs-number">120</span>px;
    padding: <span class="hljs-number">15</span>px;
}

.heading {
    text-align: center;
}

.colorTeal {
    <span class="hljs-attr">color</span>: teal;
}

.colorBlack {
    <span class="hljs-attr">color</span>: #<span class="hljs-number">1</span>b2839;
}
</code></pre>
<p><strong>Adding Users Component</strong></p>
<p>Add this code inside the <code>Users.js</code> file under the <code>src/components/Users</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

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

<span class="hljs-keyword">import</span> { useAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../contexts/auth-context"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'./Users.module.scss'</span>;

<span class="hljs-keyword">const</span> Users = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { token } = useAuth();
  <span class="hljs-keyword">const</span> [users, setUsers] = useState([]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    axios
      .get(<span class="hljs-string">"/api/users/list"</span>, {
        <span class="hljs-attr">headers</span>: {
          <span class="hljs-attr">Authorization</span>: <span class="hljs-string">`Bearer <span class="hljs-subst">${token}</span>`</span>,
        },
      })
      .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> {
        setUsers(res.data.data);
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Something went wrong."</span>, error);
      });
  }, [token]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      {users.map((user) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{user.id}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.userContainer}</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">User</span> <span class="hljs-attr">user</span>=<span class="hljs-string">{user}/</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Users;
</code></pre>
<p>In this component, we first fetch the list of users using an HTTP GET request to the <code>/api/users/list</code> endpoint passing the access token as an Authorization header. If the request is successful, we set <code>users</code> state with the user list received from the server.</p>
<p><code>Users.module.scss</code></p>
<p>Add this code inside the <code>Users.module.scss</code> file under the <code>src/components/Users</code> directory.</p>
<pre><code class="lang-javascript">.container {
    margin-top: <span class="hljs-number">150</span>px;
}

.userContainer {
    margin-bottom: <span class="hljs-number">20</span>px;
}
</code></pre>
<p><strong>Adding User Component</strong></p>
<p>Add this code inside the <code>User.js</code> file under the <code>src/components/Users/User</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'./User.module.scss'</span>;

<span class="hljs-keyword">const</span> User = <span class="hljs-function">(<span class="hljs-params">{ user }</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.imageContainer}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.image}</span>
          <span class="hljs-attr">src</span>=<span class="hljs-string">"https://img.freepik.com/free-vector/businessman-character-avatar-isolated_24877-60111.jpg"</span>
          <span class="hljs-attr">alt</span>=<span class="hljs-string">"User Avatar"</span>
        /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{user.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer
          ornare neque quis purus tempus interdum. Lorem ipsum dolor sit amet,
          consectetur adipiscing elit.{" "}
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> User;
</code></pre>
<p><code>User.module.scss</code></p>
<p>Add this code inside the <code>User.module.scss</code> file under the <code>src/components/Users/User</code> directory.</p>
<pre><code class="lang-javascript">.container {
  <span class="hljs-attr">display</span>: flex;
  max-width: <span class="hljs-number">600</span>px;
  margin: <span class="hljs-number">0</span> auto;
  gap: <span class="hljs-number">20</span>px;
  align-items: center;
  box-shadow: <span class="hljs-number">0</span> <span class="hljs-number">3</span>px <span class="hljs-number">5</span>px rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.2</span>);
  padding: <span class="hljs-number">20</span>px <span class="hljs-number">18</span>px;
}

.imageContainer {
  <span class="hljs-attr">width</span>: <span class="hljs-number">200</span>px;
  height: <span class="hljs-number">100</span>px;
  overflow: hidden;
  flex-basis: <span class="hljs-number">100</span>px;
  flex-shrink: <span class="hljs-number">0</span>;
  flex-grow: <span class="hljs-number">0</span>;
  border-radius: <span class="hljs-number">50</span>%;
}

.image {
  <span class="hljs-attr">width</span>: <span class="hljs-number">100</span>%;
  height: <span class="hljs-number">100</span>%;
  object-fit: cover;
}
</code></pre>
<p><strong>Adding routes for Home and Users components</strong></p>
<p>Update the router config in <code>App.js</code> with the new config.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useCallback, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { createBrowserRouter, RouterProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-keyword">import</span> Signup <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Signup/Signup"</span>;
<span class="hljs-keyword">import</span> Login <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Login/Login"</span>;
<span class="hljs-keyword">import</span> Home <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Home/Home"</span>;
<span class="hljs-keyword">import</span> Users <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Users/Users"</span>;

<span class="hljs-keyword">import</span> { useAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"./contexts/auth-context"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { login, logout, isAuthenticated, expiresAt } = useAuth();

  <span class="hljs-keyword">const</span> refreshAccessToken = useCallback(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.post(
        <span class="hljs-string">"/api/auth/refresh"</span>,
        {},
        {
          <span class="hljs-attr">withCredentials</span>: <span class="hljs-literal">true</span>,
        }
      );

      <span class="hljs-keyword">const</span> { user, accessToken, expiresAt } = response.data;

      <span class="hljs-keyword">if</span> (response.status === <span class="hljs-number">204</span>) {
        logout();
      } <span class="hljs-keyword">else</span> {
        login(user, accessToken, expiresAt);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      logout();
    }
  }, [login, logout]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    refreshAccessToken();
  }, [refreshAccessToken]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">let</span> refreshAccessTokenTimerId;

    <span class="hljs-keyword">if</span> (isAuthenticated) {
      refreshAccessTokenTimerId = <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        refreshAccessToken();
      }, <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(expiresAt).getTime() - <span class="hljs-built_in">Date</span>.now() - <span class="hljs-number">10</span> * <span class="hljs-number">1000</span>);
    }

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">if</span> (isAuthenticated &amp;&amp; refreshAccessTokenTimerId) {
        <span class="hljs-built_in">clearTimeout</span>(refreshAccessTokenTimerId);
      }
    };
  }, [expiresAt, isAuthenticated, refreshAccessToken]);

<span class="hljs-comment">// New code</span>
  <span class="hljs-keyword">const</span> router = createBrowserRouter([
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Home</span> /&gt;</span></span>,
    },
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"sign-up"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Signup</span> /&gt;</span></span>,
    },
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"login"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Login</span> /&gt;</span></span>,
    },
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">"users"</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Users</span> /&gt;</span></span>
    }
  ]);

<span class="hljs-comment">// Existing code</span>
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">RouterProvider</span> <span class="hljs-attr">router</span>=<span class="hljs-string">{router}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>You can now visit the home and users page by going to <code>http://localhost:3000</code> and <code>http://localhost:3000/users</code></p>
<p><strong>Home page</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685190990852/427610ea-8bac-4549-b7ea-6d672abcadba.png" alt class="image--center mx-auto" /></p>
<p><strong>Users Page</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1685191346299/ff45440c-d3bd-484f-81e0-9921debd0b7a.png" alt class="image--center mx-auto" /></p>
<p><strong>Adding Navbar</strong></p>
<p>Let's add a Navbar component that displays Login and Sign up links when the user is not logged in and displays the logout button when a user is logged in.</p>
<p><code>Navbar.js</code></p>
<p>Add this code inside the <code>Navbar.js</code> under the <code>src/components/Navbar</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Link, useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-keyword">import</span> { useAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../contexts/auth-context"</span>;

<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">"./Navbar.module.scss"</span>;

<span class="hljs-keyword">const</span> Navbar = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> { isAuthenticated, token, logout } = useAuth();
  <span class="hljs-keyword">const</span> navigate = useNavigate();

  <span class="hljs-keyword">const</span> logOutHandler = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> axios.post(
        <span class="hljs-string">"/api/auth/logout"</span>,
        {},
        {
          <span class="hljs-attr">headers</span>: {
            <span class="hljs-attr">Authorization</span>: <span class="hljs-string">`Bearer <span class="hljs-subst">${token}</span>`</span>,
          },
        }
      );
      logout();
      navigate(<span class="hljs-string">'/login'</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Something went wrong."</span>, error);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.header}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigation}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.brand}</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/"</span>&gt;</span>
            Demo App
          <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationListContainer}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationList}</span>&gt;</span>
            {!isAuthenticated &amp;&amp; (
              <span class="hljs-tag">&lt;&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationItem}</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationLink}</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/login"</span>&gt;</span>
                    Login
                  <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationItem}</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationLink}</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/sign-up"</span>&gt;</span>
                    Sign Up
                  <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;/&gt;</span>
            )}
            {isAuthenticated &amp;&amp; (
              <span class="hljs-tag">&lt;&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationItem}</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationLink}</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/users"</span>&gt;</span>
                    Users
                  <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationItem}</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                    <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.navigationLink}</span>
                    <span class="hljs-attr">onClick</span>=<span class="hljs-string">{logOutHandler}</span>
                  &gt;</span>
                    Log out
                  <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;/&gt;</span>
            )}
          <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      &lt;/nav&gt;
    &lt;/header&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Navbar;
</code></pre>
<p>There are a couple of things happening here, let me explain them step by step:</p>
<ul>
<li><p>Since we are using the <code>useAuth()</code> custom hook to handle user authentication, it provides us with a set of properties and functions to effectively manage the authentication process.</p>
</li>
<li><p>The <code>isAuthenticated</code> property is used to check if the user is authenticated or not. If the user is authenticated, we show the log-out button; otherwise, we display the login and sign-up buttons.</p>
</li>
<li><p>The <code>logOutHandler</code> is called when a user clicks on the log-out button. It sends a POST request to <code>/api/auth/logout</code> endpoint with the access token as the Authorization header and calls the <code>logout()</code> function once we get a successful response back from the server.</p>
</li>
<li><p>The <code>logout()</code> is responsible for clearing the user object from the reducer state.</p>
</li>
<li><p>After the user is logged out, we redirect them to the login page.</p>
</li>
</ul>
<p><code>Navbar.module.scss</code></p>
<p>Add this code inside the <code>Navbar.module.scss</code> file under the <code>src/components/Navbar</code> directory.</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.header</span> {
    <span class="hljs-attribute">height</span>: <span class="hljs-number">70px</span>;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">background-color</span>: white;
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">20px</span>;
    -webkit-<span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0px</span> <span class="hljs-number">8px</span> <span class="hljs-number">5px</span> <span class="hljs-number">0px</span> rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.05</span>);
    -moz-<span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0px</span> <span class="hljs-number">8px</span> <span class="hljs-number">5px</span> <span class="hljs-number">0px</span> rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.05</span>);
    <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0px</span> <span class="hljs-number">8px</span> <span class="hljs-number">5px</span> <span class="hljs-number">0px</span> rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.05</span>);
    <span class="hljs-attribute">position</span>: fixed;
    <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">right</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">z-index</span>: <span class="hljs-number">100</span>;

    <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
        <span class="hljs-attribute">height</span>: <span class="hljs-number">60px</span>;
    }
}

<span class="hljs-selector-class">.navigation</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">justify-content</span>: space-between;
    <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span>;
}

<span class="hljs-selector-class">.brand</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#1b2839</span>;
    <span class="hljs-attribute">text-decoration</span>: none;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24px</span>;
    <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">700</span>;
    <span class="hljs-attribute">text-transform</span>: uppercase;

    &amp;<span class="hljs-selector-pseudo">:hover</span> {
        <span class="hljs-attribute">color</span>: teal;
    }

    <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
        <span class="hljs-attribute">font-size</span>: <span class="hljs-number">22px</span>;
    }
}

<span class="hljs-selector-class">.navigationList</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">justify-content</span>: flex-end;
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">flex-basis</span>: <span class="hljs-number">33%</span>;

    <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
        <span class="hljs-attribute">flex-direction</span>: column;
    }
}

<span class="hljs-selector-class">.navigationItem</span> {
    <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">20px</span>;
    <span class="hljs-attribute">transition</span>: all <span class="hljs-number">5s</span>;

    <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
        <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">0</span>;
        <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">30px</span>;
    }
}

<span class="hljs-selector-class">.navigationLink</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-direction</span>: column;
    <span class="hljs-attribute">align-items</span>: center;
    <span class="hljs-attribute">justify-content</span>: center;
    <span class="hljs-attribute">color</span>: <span class="hljs-number">#1b2839</span>;
    <span class="hljs-attribute">cursor</span>: pointer;
    <span class="hljs-attribute">text-transform</span>: uppercase;
    <span class="hljs-attribute">text-decoration</span>: none;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;

    &amp;<span class="hljs-selector-pseudo">:hover</span> {
        <span class="hljs-attribute">color</span>: teal;
    }

    &amp;<span class="hljs-selector-pseudo">:hover</span> svg {
        stroke: teal;
    }

    &amp;<span class="hljs-selector-pseudo">:hover</span>&gt;<span class="hljs-selector-tag">span</span> {
        <span class="hljs-attribute">color</span>: teal;
    }

    <span class="hljs-comment">// button styles</span>
    <span class="hljs-attribute">background</span>: none;
    <span class="hljs-attribute">border</span>: none;

    <span class="hljs-keyword">@media</span> (max-width: <span class="hljs-number">768px</span>) {
        <span class="hljs-attribute">flex-direction</span>: row;

        &amp; svg {
            <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">5px</span>;
        }
    }
}
</code></pre>
<p><strong>Adding Navbar to the application</strong></p>
<p>We have two choices when it comes to adding the Navbar component to our application. First, we can add it separately to each component, like the Login, Signup, or Home page. Alternatively, we can use the Layout route and component, which allows us to group multiple routes together under a common layout.</p>
<p><strong>Adding Layout route and component</strong></p>
<p><code>Layout.js</code></p>
<p>Add this code inside the <code>Layout.js</code> file under the <code>src/components/Layout</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Outlet } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

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

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

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Layout;
</code></pre>
<p>Here we are using React Router's <code>&lt;Outlet /&gt;</code> component to render the child route components inside of the Layout component.</p>
<p><strong>(Optional) Adding Route Protection</strong></p>
<p>Currently, a user can visit the Home and Users page even if they are unauthenticated. Similarly, if a user is already authenticated, they can still visit the Login and Sign Up pages. To prevent that, let's add route protection:</p>
<p>Update the <code>App.js</code> code with this code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useCallback, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> {
  createBrowserRouter,
  RouterProvider,
  useLocation,
  Navigate,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
<span class="hljs-keyword">import</span> PropTypes <span class="hljs-keyword">from</span> <span class="hljs-string">"prop-types"</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">"axios"</span>;

<span class="hljs-keyword">import</span> Signup <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Signup/Signup"</span>;
<span class="hljs-keyword">import</span> Login <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Login/Login"</span>;
<span class="hljs-keyword">import</span> Home <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Home/Home"</span>;
<span class="hljs-keyword">import</span> Users <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Users/Users"</span>;
<span class="hljs-keyword">import</span> Layout <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/Layout/Layout"</span>;
<span class="hljs-keyword">import</span> SplashScreen <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/SplashScreen/SplashScreen"</span>;

<span class="hljs-keyword">import</span> { useAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"./contexts/auth-context"</span>;
<span class="hljs-keyword">import</span> { STATUS } <span class="hljs-keyword">from</span> <span class="hljs-string">"./utils/utils"</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { login, logout, isAuthenticated, expiresAt } = useAuth();

  <span class="hljs-keyword">const</span> refreshAccessToken = useCallback(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.post(
        <span class="hljs-string">"/api/auth/refresh"</span>,
        {},
        {
          <span class="hljs-attr">withCredentials</span>: <span class="hljs-literal">true</span>,
        }
      );

      <span class="hljs-keyword">const</span> { user, accessToken, expiresAt } = response.data;

      <span class="hljs-keyword">if</span> (response.status === <span class="hljs-number">204</span>) {
        logout();
      } <span class="hljs-keyword">else</span> {
        login(user, accessToken, expiresAt);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      logout();
    }
  }, [login, logout]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    refreshAccessToken();
  }, [refreshAccessToken]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">let</span> refreshAccessTokenTimerId;

    <span class="hljs-keyword">if</span> (isAuthenticated) {
      refreshAccessTokenTimerId = <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        refreshAccessToken();
      }, <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(expiresAt).getTime() - <span class="hljs-built_in">Date</span>.now() - <span class="hljs-number">10</span> * <span class="hljs-number">1000</span>);
    }

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-keyword">if</span> (isAuthenticated &amp;&amp; refreshAccessTokenTimerId) {
        <span class="hljs-built_in">clearTimeout</span>(refreshAccessTokenTimerId);
      }
    };
  }, [expiresAt, isAuthenticated, refreshAccessToken]);

<span class="hljs-comment">// New code</span>
  <span class="hljs-keyword">const</span> router = createBrowserRouter([
    {
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Layout</span> /&gt;</span></span>,
      children: [
        {
          <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span>,
          <span class="hljs-attr">element</span>: (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RequireAuth</span> <span class="hljs-attr">redirectTo</span>=<span class="hljs-string">"/sign-up"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Home</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">RequireAuth</span>&gt;</span></span>
          ),
        },
        {
          <span class="hljs-attr">path</span>: <span class="hljs-string">"sign-up"</span>,
          <span class="hljs-attr">element</span>: (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RedirectIfLoggedIn</span> <span class="hljs-attr">redirectTo</span>=<span class="hljs-string">"/"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Signup</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">RedirectIfLoggedIn</span>&gt;</span></span>
          ),
        },
        {
          <span class="hljs-attr">path</span>: <span class="hljs-string">"login"</span>,
          <span class="hljs-attr">element</span>: (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RedirectIfLoggedIn</span> <span class="hljs-attr">redirectTo</span>=<span class="hljs-string">"/"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Login</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">RedirectIfLoggedIn</span>&gt;</span></span>
          ),
        },
        {
          <span class="hljs-attr">path</span>: <span class="hljs-string">"users"</span>,
          <span class="hljs-attr">element</span>: (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">RequireAuth</span> <span class="hljs-attr">redirectTo</span>=<span class="hljs-string">"/sign-up"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Users</span> /&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">RequireAuth</span>&gt;</span></span>
          ),
        }
      ],
    },
  ]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">RouterProvider</span> <span class="hljs-attr">router</span>=<span class="hljs-string">{router}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-comment">// New code</span>
<span class="hljs-keyword">const</span> RequireAuth = <span class="hljs-function">(<span class="hljs-params">{ children, redirectTo }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> { isAuthenticated, status } = useAuth();
  <span class="hljs-keyword">const</span> location = useLocation();

  <span class="hljs-keyword">if</span> (status === STATUS.PENDING) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SplashScreen</span> /&gt;</span></span>;

  <span class="hljs-keyword">return</span> isAuthenticated ? (
    children
  ) : (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Navigate</span> <span class="hljs-attr">to</span>=<span class="hljs-string">{redirectTo}</span> <span class="hljs-attr">state</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">from:</span> <span class="hljs-attr">location</span> }} /&gt;</span></span>
  );
};

<span class="hljs-comment">// New code</span>
<span class="hljs-keyword">const</span> RedirectIfLoggedIn = <span class="hljs-function">(<span class="hljs-params">{ children, redirectTo }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> { isAuthenticated, status } = useAuth();
  <span class="hljs-keyword">const</span> location = useLocation();

  <span class="hljs-keyword">if</span> (status === STATUS.PENDING) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SplashScreen</span> /&gt;</span></span>;

  <span class="hljs-keyword">return</span> isAuthenticated ? (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Navigate</span> <span class="hljs-attr">to</span>=<span class="hljs-string">{location.state?.from?.pathname</span> || <span class="hljs-attr">redirectTo</span>} /&gt;</span></span>
  ) : (
    children
  );
};

RequireAuth.propTypes = {
  <span class="hljs-attr">children</span>: PropTypes.element.isRequired,
  <span class="hljs-attr">redirectTo</span>: PropTypes.string.isRequired,
};

RedirectIfLoggedIn.propTypes = {
  <span class="hljs-attr">children</span>: PropTypes.element.isRequired,
  <span class="hljs-attr">redirectTo</span>: PropTypes.string.isRequired,
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>We have added two new components to the <code>App.js</code> file 1. <code>&lt;RequireAuth /&gt;</code> and 2. <code>&lt;RedirectIfLoggedIn /&gt;</code> component. The <code>RequireAuth</code> component is used to protect routes that only an authenticated user can visit, while the <code>RedirectIfLoggedIn</code> component is used to hide routes like sign-up and login which an authenticated user cannot visit.</p>
<p><code>RequireAuth</code> <strong>Component:</strong></p>
<p>This component takes in two props: <code>children</code> and <code>redirectTo</code>. The <code>redirectTo</code> prop specifies the path to which an unauthenticated user should be redirected. It relies on the <code>isAuthenticated</code> and <code>status</code> properties returned by the <code>useAuth</code> hook to determine the user's authentication status.</p>
<p>If the user is unauthenticated, the component redirects them to the path specified in the <code>redirectTo</code> prop. On the other hand, if the user is authenticated, the component renders the child components passed through the <code>children</code> prop. If the authentication status is pending, the component displays the <code>SplashScreen</code> component.</p>
<p><code>RedirectIfLoggedIn</code> <strong>Component:</strong></p>
<p>This component also takes in two props: <code>children</code> and <code>redirectTo</code>. The <code>redirectTo</code> prop specifies the path to which an authenticated user should be redirected. It relies on the <code>isAuthenticated</code> and <code>status</code> properties returned by the <code>useAuth</code> hook to determine the user's authentication status.</p>
<p>If the user is authenticated, the component redirects them to the path specified in the <code>redirectTo</code> prop. On the other hand, if the user is unauthenticated, the component renders the child components passed through the <code>children</code> prop. If the authentication status is pending, the component displays the <code>SplashScreen</code> component.</p>
<p><code>SplashScreen</code> <strong>Component:</strong></p>
<p>Add this code inside the <code>SplashScreen.js</code> file under the <code>src/components/SplashScreen</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'./SplashScreen.module.scss'</span>;

<span class="hljs-keyword">const</span> SplashScreen = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.container}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{styles.iconContainer}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            ...loading
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> SplashScreen;
</code></pre>
<p><code>SplashScreen.module.scss</code></p>
<p>Add this code inside the <code>SplashScreen.module.scss</code> file under the <code>src/components/SplashScreen</code> directory.</p>
<pre><code class="lang-javascript">.container {
    background-color: #fff;
    color: teal;
    position: fixed;
    top: <span class="hljs-number">0</span>;
    left: <span class="hljs-number">0</span>;
    height: <span class="hljs-number">100</span>%;
    width: <span class="hljs-number">100</span>%;
    z-index: <span class="hljs-number">999</span>;
}

.iconContainer {
    <span class="hljs-attr">position</span>: absolute;
    top: <span class="hljs-number">50</span>%;
    left: <span class="hljs-number">50</span>%;
    translate: (<span class="hljs-number">-50</span>%, <span class="hljs-number">-50</span>%);
    color: teal;
}
</code></pre>
<h3 id="heading-final-result">Final Result</h3>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/I6zySlwNF3E">https://youtu.be/I6zySlwNF3E</a></div>
<p> </p>
<h3 id="heading-source-code">Source Code</h3>
<p>You can download the source code from my GitHub repo:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/SukhjinderArora/refresh-token-auth-app/">https://github.com/SukhjinderArora/refresh-token-auth-app/</a></div>
<p> </p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>So we have learned how to implement refresh and access token-based authentication in React and NodeJS. We have learned the difference between access and refresh tokens, and how to perform silent authentication by refreshing access tokens in the background. We have also learned how to protect routes in React applications using React Router.</p>
<p>That’s it and hope you found this article helpful! Please feel free to comment below and ask anything, suggest feedback or just chat. You can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora"><strong>Hashnode</strong></a>, <a target="_blank" href="https://medium.com/@sukhjinder"><strong>Medium</strong></a> and <a target="_blank" href="https://twitter.com/_sukh_arora"><strong>Twitter</strong></a>. Cheers! ⭐️</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Promises in JavaScript]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/understanding-promises-in-javascript-c5248de9ff8f
JavaScript is a single-threaded programming language, which means only one thing can happen at a time. Before ES6, we used callbacks to...]]></description><link>https://whatisweb.dev/understanding-promises-in-javascript-c5248de9ff8f</link><guid isPermaLink="true">https://whatisweb.dev/understanding-promises-in-javascript-c5248de9ff8f</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Tue, 07 Feb 2023 15:14:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/842ofHC6MaI/upload/ba0dddb8a6e03df5b05874d15a37d032.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at:</em></strong> <a target="_blank" href="https://blog.bitsrc.io/understanding-promises-in-javascript-c5248de9ff8f"><strong><em>https://blog.bitsrc.io/understanding-promises-in-javascript-c5248de9ff8f</em></strong></a></p>
<p>JavaScript is a single-threaded programming language, which means only one thing can happen at a time. Before ES6, we used callbacks to handle asynchronous tasks such as network requests.</p>
<p>Using promises, we can avoid the infamous ‘callback hell’ and make our code cleaner, easier to read, and easier to understand.</p>
<p>Suppose we want to get some data from a server asynchronously, using callbacks we would do something like this:</p>
<pre><code class="lang-javascript">getData(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>)</span>{  
    <span class="hljs-built_in">console</span>.log(x);  
    getMoreData(x, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">y</span>)</span>{  
        <span class="hljs-built_in">console</span>.log(y);   
        getSomeMoreData(y, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">z</span>)</span>{   
            <span class="hljs-built_in">console</span>.log(z);  
        });  
    });  
});
</code></pre>
<p>Here I am requesting some data from the server by calling the <code>getData()</code> function, which receives the data inside the callback function. Inside the callback function, I am requesting some more data by calling the <code>getMoreData()</code> function passing the previously received data as an argument and so on.</p>
<p>This is what we call callback hell, where each callback is nested inside another callback, and each inner callback is dependent on its parent.</p>
<p>We can rewrite the above snippet using promises. For example:</p>
<pre><code class="lang-javascript">getData()  
  .then(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> {  
    <span class="hljs-built_in">console</span>.log(x);  
    <span class="hljs-keyword">return</span> getMoreData(x);  
  })  
  .then(<span class="hljs-function">(<span class="hljs-params">y</span>) =&gt;</span> {  
    <span class="hljs-built_in">console</span>.log(y);  
    <span class="hljs-keyword">return</span> getSomeMoreData(y);  
  })  
  .then(<span class="hljs-function">(<span class="hljs-params">z</span>) =&gt;</span> {  
    <span class="hljs-built_in">console</span>.log(z);  
   });
</code></pre>
<p>We can see that this is much cleaner and easier to understand than the callbacks example above it.</p>
<h3 id="heading-what-is-a-promise">What is a Promise?</h3>
<p>A Promise is an object that holds the future value of an async operation. For example, if we are requesting some data from a server, the promise promises us to get that data that we can use in the future.</p>
<p>Before we get into all the technical stuff, let’s understand the terminology of a Promise.</p>
<h4 id="heading-states-of-a-promise">States of a Promise</h4>
<p>A Promise in JavaScript just like a promise in the real world has 3 states. It can be 1) unresolved (pending), 2) resolved (fulfilled), or 3) rejected. For example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198509534/8dTL4afRy.png" alt class="image--center mx-auto" /></p>
<p>States of Promise</p>
<ul>
<li><p><strong>Unresolved or Pending</strong> — A Promise is pending if the result is not ready. That is, it’s waiting for something to finish (for example, an async operation).</p>
</li>
<li><p><strong>Resolved or Fulfilled</strong> — A Promise is resolved if the result is available. That is, something finished (for example, an async operation) and all went well.</p>
</li>
<li><p><strong>Rejected</strong> — A Promise is rejected if an error happened.</p>
</li>
</ul>
<p>Now that we know what a Promise is, and Promise terminology, let’s get back to the practical side of the Promises.</p>
<h3 id="heading-creating-a-promise">Creating a Promise</h3>
<p>Most of the time you will be consuming promises rather than creating them, but it’s still important to know how to create them.</p>
<h4 id="heading-syntax">Syntax:</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
...
});
</code></pre>
<p>We create a new promise using the Promise constructor it takes a single argument, a callback, also known as the executor function which takes two callbacks, resolve and reject.</p>
<p>The executor function is immediately executed when a promise is created. The promise is resolved by calling the <code>resolve()</code> and rejected by calling <code>reject()</code>. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span>(allWentWell) {
        resolve(<span class="hljs-string">'All things went well!'</span>);
    } <span class="hljs-keyword">else</span> {
        reject(<span class="hljs-string">'Something went wrong'</span>);
    }
});
</code></pre>
<p>The <code>resolve()</code> and <code>reject()</code> takes one argument which can be a string, number, boolean, array or object.</p>
<p>Let’s look at another example to fully understand the promise creation.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> randomNumber = <span class="hljs-built_in">Math</span>.random();
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span>(randomNumber &lt; <span class="hljs-number">.6</span>) {
            resolve(<span class="hljs-string">'All things went well!'</span>);
        } <span class="hljs-keyword">else</span> {
            reject(<span class="hljs-string">'Something went wrong'</span>);
        }
    }, <span class="hljs-number">2000</span>);
});
</code></pre>
<p>Here I am creating a new promise using the Promise constructor. The promise is resolved or rejected after 2 seconds of its creation. The promise is resolved if the <code>randomNumber</code> is less than <code>.6</code> and rejected otherwise.</p>
<p>When the promise is created, it will be in the pending state, and its value will be <code>undefined</code>. For example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198510947/Skimi5Ttr.png" alt /></p>
<p><em>Promise status pending</em></p>
<p>After the 2 seconds timer finishes, the promise is either resolved or rejected randomly, and its value will be the value passed to the resolve or reject function. For example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198512128/-1K6eywm5.png" alt /></p>
<p><em>Promise status resolved</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198513283/mynB7wTHq.png" alt /></p>
<p><em>Promise status rejected</em></p>
<p><strong>Note</strong> — A promise can be resolved or rejected only once. Further invocation of <code>resolve()</code> or <code>reject()</code> has no effect on the Promise state. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    resolve(<span class="hljs-string">'Promise resolved'</span>); <span class="hljs-comment">// Promise is resolved</span>
    reject(<span class="hljs-string">'Promise rejected'</span>); <span class="hljs-comment">// Promise can't be rejected</span>
});
</code></pre>
<p>Since <code>resolve()</code> is called first so the Promise will be resolved. Calling <code>reject()</code> after that will have no effect on the Promise state.</p>
<h3 id="heading-consuming-a-promise">Consuming a Promise</h3>
<p>Now that we know how to create a promise, let’s understand how to consume an already-created promise. We consume a promise by calling <code>then()</code> and <code>catch()</code> methods on the promise.</p>
<p>For example, requesting data from an API using fetch which returns a promise.</p>
<p><code>**.then()**</code> <strong>syntax</strong>: <code>promise.then(successCallback, failureCallback)</code></p>
<p>The <code>successCallback</code> is called when a promise is resolved. It takes one argument which is the value passed to <code>resolve()</code>.</p>
<p>The <code>failureCallback</code> is called when a promise is rejected. It takes one argument which is the value passed to <code>reject()</code>.</p>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> randomNumber = <span class="hljs-built_in">Math</span>.random();
    <span class="hljs-keyword">if</span>(randomNumber &lt; <span class="hljs-number">.7</span>) {
        resolve(<span class="hljs-string">'All things went well!'</span>);
    } <span class="hljs-keyword">else</span> {
        reject(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Something went wrong'</span>));
    }
});

promise.then(
    <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(data); <span class="hljs-comment">// prints 'All things went well!'</span>
    },
    <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(error); <span class="hljs-comment">// prints Error object</span>
    }
);
</code></pre>
<p>Here if the promise is resolved, the <code>successCallback</code> is called with the value passed to <code>resolve()</code>. And if the promise is rejected, the <code>failureCallback</code> is called with the value passed to <code>reject()</code>.</p>
<p><code>**.catch()**</code> <strong>syntax</strong>: <code>promise.catch(failureCallback)</code></p>
<p>We use <code>catch()</code> for handling errors. It’s more readable than handling errors inside the <code>failureCallback</code> callback of the <code>then()</code> callback. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    reject(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Something went wrong'</span>));
});

promise
.then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
})
.catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(error); <span class="hljs-comment">// prints Error object</span>
});
</code></pre>
<h3 id="heading-promise-chaining">Promise Chaining</h3>
<p>The <code>then()</code> and <code>catch()</code> methods can also return a new promise which can be handled by chaining another <code>then()</code> at the end of the previous <code>then()</code> method.</p>
<p>We use promise chaining when we want to resolve promises in a sequence.</p>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    resolve(<span class="hljs-string">'Promise1 resolved'</span>);
});

<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    resolve(<span class="hljs-string">'Promise2 resolved'</span>);
});

<span class="hljs-keyword">const</span> promise3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    reject(<span class="hljs-string">'Promise3 rejected'</span>);
});

promise1
.then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data); <span class="hljs-comment">// Promise1 resolved</span>
    <span class="hljs-keyword">return</span> promise2;
})
.then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data); <span class="hljs-comment">// Promise2 resolved</span>
    <span class="hljs-keyword">return</span> promise3;
})
.then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
})
.catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(error); <span class="hljs-comment">// Promise3 rejected</span>
});
</code></pre>
<h4 id="heading-so-whats-happening-here">So what’s happening here?</h4>
<ul>
<li><p>When <code>promise1</code> is resolved, the <code>then()</code> method is called which returns <code>promise2</code>.</p>
</li>
<li><p>The next <code>then()</code> is called when <code>promise2</code> is resolved which returns <code>promise3</code>.</p>
</li>
<li><p>Since <code>promise3</code> is rejected, the next <code>then()</code> is not called instead <code>catch()</code> is called which handles the <code>promise3</code> rejection.</p>
</li>
</ul>
<p><strong>Note</strong> — Generally only one <code>catch()</code> is enough for handling the rejection of any promise in the promise chain, if it’s at the end of the chain.</p>
<h4 id="heading-common-mistake">Common Mistake</h4>
<p>A lot of beginners make the mistake of nesting promises inside another promise. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    resolve(<span class="hljs-string">'Promise1 resolved'</span>);
});

<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    resolve(<span class="hljs-string">'Promise2 resolved'</span>);
});

<span class="hljs-keyword">const</span> promise3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    reject(<span class="hljs-string">'Promise3 rejected'</span>);
});

promise1.then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data); <span class="hljs-comment">// Promise1 resolved</span>

    promise2.then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(data); <span class="hljs-comment">// Promise2 resolved</span>

        promise3.then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
            <span class="hljs-built_in">console</span>.log(data);
        }).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
            <span class="hljs-built_in">console</span>.log(error); <span class="hljs-comment">// Promise3 rejected</span>
        });

    }).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(error);
    })

}).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(error);
});
</code></pre>
<p>Although this works fine, this is considered to be a poor style and makes our code difficult to read. If you have a sequence of promises to resolve, it’s better to chain promises one after another rather than nest one inside another.</p>
<h3 id="heading-promiseall">Promise.all( )</h3>
<p>This method takes an array of promises as input and returns a new promise that fulfills when all of the promises inside the input array have been fulfilled or rejected as soon as one of the promises in the array rejects. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        resolve(<span class="hljs-string">'Promise1 resolved'</span>);
    }, <span class="hljs-number">2000</span>);
});

<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        resolve(<span class="hljs-string">'Promise2 resolved'</span>);
    }, <span class="hljs-number">1500</span>);
});

<span class="hljs-built_in">Promise</span>.all([promise1, promise2])
    .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(data[<span class="hljs-number">0</span>], data[<span class="hljs-number">1</span>]))
    .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(error));
</code></pre>
<ul>
<li><p>Here the data argument inside the <code>then()</code> method is an array that contains promise values in the same order as defined in the promise array passed to <code>Promise.all()</code> (if all promises fulfill).</p>
</li>
<li><p>The promise is rejected with the reason of rejection from the first rejected promise in the input array. For example:</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        resolve(<span class="hljs-string">'Promise1 resolved'</span>);
    }, <span class="hljs-number">2000</span>);
});

<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        reject(<span class="hljs-string">'Promise2 rejected'</span>);
    }, <span class="hljs-number">1500</span>);
});

<span class="hljs-built_in">Promise</span>.all([promise1, promise2])
    .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(data[<span class="hljs-number">0</span>], data[<span class="hljs-number">1</span>]))
    .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(error)); <span class="hljs-comment">// Promise2 rejected</span>
</code></pre>
<ul>
<li><p>Here we have two promises where one is resolved after 2 seconds, and the other is rejected after 1.5 seconds.</p>
</li>
<li><p>As soon as the second promise is rejected after 1.5 seconds, the returned promise from <code>Promise.all()</code> is rejected without waiting for the first promise to be resolved.</p>
</li>
</ul>
<p>This method can be useful when you have more than one promise, and you want to know when all of the promises have been resolved. For example, if you are requesting data from different APIs and you want to do something with the data only when all of the requests are successful.</p>
<p>So <code>Promise.all()</code> waits for all promises to succeed and fails if any of the promises in the array fails.</p>
<h3 id="heading-promiserace">Promise.race( )</h3>
<p>This method takes an array of promises as input and returns a new promise that fulfills as soon as one of the promises in the input array fulfills or rejects as soon as one of the promises in the input array rejects. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        resolve(<span class="hljs-string">'Promise1 resolved'</span>);
    }, <span class="hljs-number">1000</span>);
});

<span class="hljs-keyword">const</span> promise2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
        reject(<span class="hljs-string">'Promise2 rejected'</span>);
    }, <span class="hljs-number">1500</span>);
});

<span class="hljs-built_in">Promise</span>.race([promise1, promise2])
    .then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(data)) <span class="hljs-comment">// Promise1 resolved</span>
    .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(error));
</code></pre>
<ul>
<li><p>Here we have two promises where one is resolved after 1 second, and the other is rejected after 1.5 seconds.</p>
</li>
<li><p>As soon as the first promise is resolved after 1 second, the returned promise from <code>Promise.race()</code> is resolved without waiting for the second promise to be resolved or rejected.</p>
</li>
<li><p>Here data passed to the <code>then()</code> method is the value of the first promise that resolves.</p>
</li>
</ul>
<p>So <code>Promise.race()</code> waits for one of the promises in the array to succeed or fail and fulfills or rejects as soon as one of the promises in the array is resolved or rejected.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We have learned what promises are and how to use them in JavaScript. A Promise has two parts 1) Promise creation and 2) consuming a Promise. Most of the time you will be consuming promises rather than creating them, but it’s still important to know how to create them.</p>
<p>That’s it and hope you found this article helpful! Please feel free to comment below and ask anything, suggest feedback or just chat. Cheers! ⭐️</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Call, Bind and Apply Methods in JavaScript]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/understanding-call-bind-and-apply-methods-in-javascript-33dbf3217be
If you are learning JavaScript, you might have seen the this keyword. The this keyword in JavaScript behaves differen...]]></description><link>https://whatisweb.dev/understanding-call-bind-and-apply-methods-in-javascript</link><guid isPermaLink="true">https://whatisweb.dev/understanding-call-bind-and-apply-methods-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Sun, 29 Jan 2023 10:51:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/IGfoMhQhtwo/upload/b6a7facf977f6bbd8e8cb5ad4605fe5a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at:</em></strong> <a target="_blank" href="https://blog.bitsrc.io/understanding-call-bind-and-apply-methods-in-javascript-33dbf3217be"><strong><em>https://blog.bitsrc.io/understanding-call-bind-and-apply-methods-in-javascript-33dbf3217be</em></strong></a></p>
<p>If you are learning JavaScript, you might have seen the <code>this</code> keyword. The <code>this</code> keyword in JavaScript behaves differently compared to other programming languages. This causes a lot of confusion for programmers.</p>
<p>In other object-oriented programming languages, the <code>this</code> keyword always refers to the current instance of the class. Whereas in JavaScript, the value of <code>this</code> depends on how a function is called.</p>
<p>Let’s look at some examples to demonstrate the behavior of <code>this</code> in JavaScript.</p>
<h4 id="heading-example-1">Example 1:</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> person = {  
  <span class="hljs-attr">firstName</span>: <span class="hljs-string">'John'</span>,  
  <span class="hljs-attr">lastName</span>: <span class="hljs-string">'Doe'</span>,  
  <span class="hljs-attr">printName</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>.firstName + <span class="hljs-string">' '</span> + <span class="hljs-built_in">this</span>.lastName);  
  }  
};
</code></pre>
<p>Now let’s execute the <code>printName</code> method.</p>
<pre><code class="lang-javascript">person.printName();
</code></pre>
<p>This prints:</p>
<pre><code class="lang-javascript">John Doe
</code></pre>
<p>Here, I am calling the <code>printName()</code> method using the <code>person</code> object, so the <code>this</code> keyword inside the method refers to the <code>person</code> object.</p>
<p>Let’s write the below snippet at the end of the above code.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> printFullName = person.printName;  
printFullName();
</code></pre>
<p>What do you think the <strong>console.log</strong> will now output? Surprisingly, this prints:</p>
<pre><code class="lang-javascript"><span class="hljs-literal">undefined</span> <span class="hljs-literal">undefined</span>
</code></pre>
<p><strong>Why does this happen?</strong></p>
<p>Here, we are storing a reference of <code>person.printName</code> to <code>printFullName</code> variable. After that, we are calling it without an object reference, so <code>this</code> will now refer to the window (global) object or undefined (in strict mode).</p>
<p>If the script is in strict mode, <code>this</code> refers to <code>undefined</code>, so <code>console.log()</code> will return an error.</p>
<h4 id="heading-example-2">Example 2:</h4>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> counter = {  
  <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,  
  <span class="hljs-attr">incrementCounter</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>);  
    <span class="hljs-built_in">this</span>.count++;  
  }  
}

<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.btn'</span>).addEventListener(<span class="hljs-string">'click'</span>, counter.incrementCounter);
</code></pre>
<p>What would be the value of <code>this</code> inside <code>incrementCounter()</code> method?</p>
<p>In the above snippet, the <code>this</code> keyword refers to the DOM element where the event happened, not the <code>counter</code> object.</p>
<p>So we can see that the <code>this</code> keyword inside a function refers to different objects depending on how the function is called and sometimes we accidentally lose reference to the <code>this</code> variable. So how can we prevent that from happening?</p>
<h3 id="heading-call-bind-and-apply-to-rescue">Call( ), Bind( ), and Apply( ) to Rescue</h3>
<p>We use Call, Bind and Apply methods to set the <code>this</code> keyword independent of how the function is called. This is especially useful for the callbacks (as in the above example).</p>
<p>We know that functions are a special kind of objects in JavaScript. So they have access to the same methods and properties as objects. To prove functions are objects, we can do something like this, for example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greeting</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello World'</span>);  
}

greeting.lang = <span class="hljs-string">'English'</span>;

<span class="hljs-comment">// Prints 'English'  </span>
<span class="hljs-built_in">console</span>.log(greeting.lang);
</code></pre>
<p>JavaScript also provides some special methods and properties to every function object. So every function in JavaScript inherits those methods. Call, bind, and apply are some of the methods that every function inherits.</p>
<h3 id="heading-bind">Bind( )</h3>
<p>The bind method creates a new function and sets the <code>this</code> keyword to the specified object.</p>
<h4 id="heading-syntax">Syntax:</h4>
<pre><code class="lang-javascript"><span class="hljs-string">`function`</span>.bind(thisArg, optionalArguments)
</code></pre>
<p>For example:</p>
<p>Let’s suppose we have two person objects.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> john = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>,  
  <span class="hljs-attr">age</span>: <span class="hljs-number">24</span>,  
};

<span class="hljs-keyword">const</span> jane = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Jane'</span>,  
  <span class="hljs-attr">age</span>: <span class="hljs-number">22</span>,  
};
</code></pre>
<p>Let’s add a greeting function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greeting</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hi, I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> and I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.age}</span> years old`</span>);  
}
</code></pre>
<p>We can use the <code>bind</code> method on the <code>greeting</code> function to bind the <code>this</code> keyword to <code>john</code> and <code>jane</code> objects. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> greetingJohn = greeting.bind(john);

<span class="hljs-comment">// Hi, I am John and I am 24 years old  </span>
greetingJohn();

<span class="hljs-keyword">const</span> greetingJane = greeting.bind(jane);

<span class="hljs-comment">// Hi, I am Jane and I am 22 years old  </span>
greetingJane();
</code></pre>
<p>Here <code>greeting.bind(john)</code> creates a new function with <code>this</code> set to <code>john</code> object, which we then assign to <code>greetingJohn</code> variable.</p>
<p>We can also use <code>bind</code> in case of callbacks and event handlers. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> counter = {  
  <span class="hljs-attr">count</span>: <span class="hljs-number">0</span>,  
  <span class="hljs-attr">incrementCounter</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>);  
    <span class="hljs-built_in">this</span>.count++;  
  }  
};

<span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.btn'</span>).addEventListener(<span class="hljs-string">'click'</span>, counter.incrementCounter.bind(counter));
</code></pre>
<p>In the above example, the <code>this</code> keyword inside the <code>incrementCounter</code> method will now correctly refer to the <code>counter</code> object instead of the event object.</p>
<h4 id="heading-bind-can-also-accept-arguments">Bind() can also accept arguments</h4>
<p>We can also pass extra arguments to the bind method. The general syntax for this is <code>function.bind(this, arg1, arg2, ...)</code>. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greeting</span>(<span class="hljs-params">lang</span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${lang}</span>: I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span>`</span>);  
}

<span class="hljs-keyword">const</span> john = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>  
};

<span class="hljs-keyword">const</span> jane = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Jane'</span>  
};

<span class="hljs-keyword">const</span> greetingJohn = greeting.bind(john, <span class="hljs-string">'en'</span>);  
greetingJohn();

<span class="hljs-keyword">const</span> greetingJane = greeting.bind(jane, <span class="hljs-string">'es'</span>);  
greetingJane();
</code></pre>
<p>In the above example, the <code>bind</code> method creates a new function with certain parameters predefined (<code>lang</code> in this case) and <code>this</code> keyword set to the <code>john</code> and <code>jane</code> objects.</p>
<h3 id="heading-call">Call ( )</h3>
<p>The call method sets the <code>this</code> inside the function and immediately executes that function.</p>
<p>The difference between <code>call()</code> and <code>bind()</code> is that the <code>call()</code> sets the <code>this</code> keyword and executes the function immediately and it does not create a new copy of the function, while the <code>bind()</code> creates a copy of that function and sets the <code>this</code> keyword.</p>
<h4 id="heading-syntax-1">Syntax:</h4>
<pre><code class="lang-javascript"><span class="hljs-string">`function`</span>.call(thisArg, arg1, agr2, ...)
</code></pre>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greeting</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Hi, I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> and I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.age}</span> years old`</span>);  
}

<span class="hljs-keyword">const</span> john = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>,  
  <span class="hljs-attr">age</span>: <span class="hljs-number">24</span>,  
};

<span class="hljs-keyword">const</span> jane = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Jane'</span>,  
  <span class="hljs-attr">age</span>: <span class="hljs-number">22</span>,  
};

<span class="hljs-comment">// Hi, I am John and I am 24 years old  </span>
greeting.call(john);

<span class="hljs-comment">// Hi, I am Jane and I am 22 years old  </span>
greeting.call(jane);
</code></pre>
<p>The above example is similar to the <code>bind()</code> example except that <code>call()</code> does not create a new function. We are directly setting the <code>this</code> keyword using <code>call()</code>.</p>
<h4 id="heading-call-can-also-accept-arguments">Call () can also accept arguments</h4>
<p><code>Call()</code> also accepts a comma-separated list of arguments. The general syntax for this is <code>function.call(this, arg1, arg2, ...)</code></p>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">greeting</span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${greeting}</span>, I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> and I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.age}</span> years old`</span>);  
}

<span class="hljs-keyword">const</span> john = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>,  
  <span class="hljs-attr">age</span>: <span class="hljs-number">24</span>,  
};

<span class="hljs-keyword">const</span> jane = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Jane'</span>,  
  <span class="hljs-attr">age</span>: <span class="hljs-number">22</span>,  
};

<span class="hljs-comment">// Hi, I am John and I am 24 years old  </span>
greet.call(john, <span class="hljs-string">'Hi'</span>);

<span class="hljs-comment">// Hello, I am Jane and I am 22 years old  </span>
greet.call(jane, <span class="hljs-string">'Hello'</span>);
</code></pre>
<h3 id="heading-apply">Apply ( )</h3>
<p>The <code>apply()</code> method is similar to <code>call()</code>. The difference is that the <code>apply()</code> method accepts an array of arguments instead of comma-separated values.</p>
<h4 id="heading-syntax-2">Syntax:</h4>
<pre><code class="lang-javascript"><span class="hljs-string">`function`</span>.apply(thisArg, [argumentsArr])
</code></pre>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">greeting, lang</span>) </span>{  
  <span class="hljs-built_in">console</span>.log(lang);  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${greeting}</span>, I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.name}</span> and I am <span class="hljs-subst">${<span class="hljs-built_in">this</span>.age}</span> years old`</span>);  
}

<span class="hljs-keyword">const</span> john = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>,  
  <span class="hljs-attr">age</span>: <span class="hljs-number">24</span>,  
};

<span class="hljs-keyword">const</span> jane = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Jane'</span>,  
  <span class="hljs-attr">age</span>: <span class="hljs-number">22</span>,  
};

<span class="hljs-comment">// en</span>
<span class="hljs-comment">// Hi, I am John and I am 24 years old  </span>
greet.apply(john, [<span class="hljs-string">'Hi'</span>, <span class="hljs-string">'en'</span>]);

<span class="hljs-comment">// es</span>
<span class="hljs-comment">// Hola, I am Jane and I am 22 years old  </span>
greet.apply(jane, [<span class="hljs-string">'Hola'</span>, <span class="hljs-string">'es'</span>]);
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We have learned how <code>this</code> keyword behaves differently in JavaScript than in other object-oriented languages. The call, bind and apply methods can be used to set the <code>this</code> keyword independent of how a function is called.</p>
<p>The bind method creates a copy of the function and sets the <code>this</code> keyword, while the call and apply methods set the <code>this</code> keyword and calls the function immediately.</p>
<p>That’s it and if you found this article helpful, please click the like 🙂 button, you can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora">Hashnode</a>, <a target="_blank" href="https://medium.com/@sukhjinder">Medium</a> and <a target="_blank" href="https://twitter.com/_sukh_arora">Twitter</a>, and if you have any doubt, feel free to comment! I’d be happy to help :)</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Design Patterns in JavaScript]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/understanding-design-patterns-in-javascript-13345223f2dd
When you start a new project, you don’t immediately start coding. You first have to define the purpose and scope of the project,...]]></description><link>https://whatisweb.dev/understanding-design-patterns-in-javascript-13345223f2dd</link><guid isPermaLink="true">https://whatisweb.dev/understanding-design-patterns-in-javascript-13345223f2dd</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Wed, 18 Jan 2023 04:47:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/mDinBvq1Sfg/upload/v1668870970701/Wikyb_4vp.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at: https://blog.bitsrc.io/understanding-design-patterns-in-javascript-13345223f2dd</em></strong></p>
<p>When you start a new project, you don’t immediately start coding. You first have to define the purpose and scope of the project, then list out the project features or specs. After you can either start coding or if you are working on a more complex project then you should choose a design pattern that best suits your project.</p>
<h3 id="heading-what-is-a-design-pattern">What is a Design Pattern?</h3>
<p>In software engineering, a design pattern is a reusable solution for commonly occurring problems in software design. Design patterns represent the best practices used by experienced software developers. A design pattern can be thought of as a programming template.</p>
<h4 id="heading-why-use-design-patterns">Why use Design Patterns?</h4>
<p>Many programmers either think design patterns are a waste of time or they don’t know how to apply them appropriately. But using an appropriate design pattern can help you to write better and more understandable code, and the code can be easily maintained because it’s easier to understand.</p>
<p>Most importantly, the design patterns give software developers a common vocabulary to talk about. They show the intent of your code instantly to someone learning the code.</p>
<p>For example, if you are using decorator pattern in your project, then a new programmer would immediately know what that piece of code is doing, and they can focus more on solving the business problem rather than trying to understand what that code is doing.</p>
<p>Now that we know what design patterns are, and why they are important, let’s dive into various design patterns used in JavaScript.</p>
<h3 id="heading-module-pattern">Module Pattern</h3>
<p>A Module is a piece of self-contained code so we can update the Module without affecting the other parts of the code. Modules also allow us to avoid namespace pollution by creating a separate scope for our variables. We can also reuse modules in other projects when they are decoupled from other pieces of code.</p>
<p>Modules are an integral part of any modern JavaScript application and help in keeping our code clean, separated and organized. There are many ways to create modules in JavaScript, one of which is the Module pattern.</p>
<p>Unlike other programming languages, JavaScript doesn’t have access modifiers, that is, you can’t declare a variable as private or public. So the Module pattern is also used to emulate the concept of encapsulation.</p>
<p>This pattern uses IIFE (immediately-invoked function expression), closures and function scope to simulate this concept. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myModule = (<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">const</span> privateVariable = <span class="hljs-string">'Hello World'</span>;

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">privateMethod</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-built_in">console</span>.log(privateVariable);  
  }

  <span class="hljs-keyword">return</span> {  
    <span class="hljs-attr">publicMethod</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
      privateMethod();  
    }  
  }

})();

myModule.publicMethod();
</code></pre>
<p>As it’s IIFE, the code is immediately executed, and the returned object is assigned to the <code>myModule</code> variable. Due to closures, the returned object can still access the functions and variables defined inside the IIFE even after when IIFE has finished.</p>
<p>So the variables and functions defined inside the IIFE are essentially hidden from the outer scope and thus making it private to the <code>myModule</code> variable.</p>
<p>After the code is executed, the <code>myModule</code> variable looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myModule = {  
  <span class="hljs-attr">publicMethod</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    privateMethod();  
  }
};
</code></pre>
<p>So we can call the <code>publicMethod()</code> which will, in turn, call the <code>privateMethod()</code>. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Prints 'Hello World'  </span>
<span class="hljs-built_in">module</span>.publicMethod();
</code></pre>
<h3 id="heading-revealing-module-pattern">Revealing Module Pattern</h3>
<p>The Revealing Module pattern is a slightly improved version of the module pattern by Christian Heilmann. The problem with the module pattern is that we have to create new public functions just to call the private functions and variables.</p>
<p>In this pattern, we map the returned object’s properties to the private functions that we want to reveal as public. That’s why it’s called the Revealing Module pattern. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myRevealingModule = (<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-keyword">let</span> privateVar = <span class="hljs-string">'Peter'</span>;  
  <span class="hljs-keyword">const</span> publicVar = <span class="hljs-string">'Hello World'</span>;

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">privateFunction</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Name: '</span>+ privateVar);  
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">publicSetName</span>(<span class="hljs-params">name</span>) </span>{  
    privateVar = name;  
  }

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">publicGetName</span>(<span class="hljs-params"></span>) </span>{  
    privateFunction();  
  }

<span class="hljs-comment">/* reveal methods and variables by assigning them to object properties */</span>

  <span class="hljs-keyword">return</span> {  
    <span class="hljs-attr">setName</span>: publicSetName,  
    <span class="hljs-attr">greeting</span>: publicVar,  
    <span class="hljs-attr">getName</span>: publicGetName  
  };

})();

myRevealingModule.setName(<span class="hljs-string">'Mark'</span>);

<span class="hljs-comment">// prints Name: Mark  </span>
myRevealingModule.getName();
</code></pre>
<p>This pattern makes it easier to understand which of our functions and variables can be accessed publicly, which helps in code readability.</p>
<p>After the code is executed, the <code>myRevealingModule</code> looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myRevealingModule = {  
  <span class="hljs-attr">setName</span>: publicSetName,  
  <span class="hljs-attr">greeting</span>: publicVar,  
  <span class="hljs-attr">getName</span>: publicGetName  
};
</code></pre>
<p>We can call <code>myRevealingModule.setName('Mark')</code>, which is a reference to the inner <code>publicSetName</code> and <code>myRevealingModule.getName()</code>, which is a reference to the inner <code>publicGetName</code>. For example:</p>
<pre><code class="lang-javascript">myRevealingModule.setName(<span class="hljs-string">'Mark'</span>);

<span class="hljs-comment">// prints Name: Mark  </span>
myRevealingModule.getName();
</code></pre>
<p><strong>Advantages of Revealing Module pattern over Module Pattern:</strong></p>
<ul>
<li><p>We can change public members to private and vice versa by modifying a single line in the return statement.</p>
</li>
<li><p>The returned object contains no function definitions, all right-hand side expressions are defined inside the IIFE, making the code clear and easy to read.</p>
</li>
</ul>
<h3 id="heading-es6-modules">ES6 Modules</h3>
<p>Before ES6, JavaScript didn’t have built-in modules, so developers had to rely on third-party libraries or the module pattern to implement modules. But with ES6, JavaScript has native modules.</p>
<p>ES6 modules are stored in files. There can only be one module per file. Everything inside a module is private by default. Functions, variables, and classes are exposed using the <code>export</code> keyword. The code inside a module always runs in strict mode.</p>
<h4 id="heading-exporting-a-module">Exporting a Module</h4>
<p>There are two ways to export a function and variable declaration:</p>
<ul>
<li>By adding the <code>export</code> keyword in front of the function and variable declaration. For example:</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// utils.js</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> greeting = <span class="hljs-string">'Hello World'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params">num1, num2</span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Sum:'</span>, num1, num2);  
  <span class="hljs-keyword">return</span> num1 + num2;  
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">subtract</span>(<span class="hljs-params">num1, num2</span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Subtract:'</span>, num1, num2);  
  <span class="hljs-keyword">return</span> num1 - num2;  
}

<span class="hljs-comment">// This is a private function</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">privateLog</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Private Function'</span>);  
}
</code></pre>
<ul>
<li>By adding the <code>export</code> keyword at end of the code containing names of functions and variables we want to export. For example:</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// utils.js</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiply</span>(<span class="hljs-params">num1, num2</span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Multiply:'</span>, num1, num2);  
  <span class="hljs-keyword">return</span> num1 \* num2;  
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">divide</span>(<span class="hljs-params">num1, num2</span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Divide:'</span>, num1, num2);  
  <span class="hljs-keyword">return</span> num1 / num2;  
}

<span class="hljs-comment">// This is a private function</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">privateLog</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Private Function'</span>);  
}

<span class="hljs-keyword">export</span> {multiply, divide};
</code></pre>
<h4 id="heading-importing-a-module">Importing a Module</h4>
<p>Similar to exporting a module, there are two ways to import a module by using the <code>import</code> keyword. For example:</p>
<ul>
<li><strong>Importing multiple items at one time</strong></li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// main.js</span>

<span class="hljs-comment">// importing multiple items  </span>
<span class="hljs-keyword">import</span> { sum, multiply } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils.js'</span>;

<span class="hljs-built_in">console</span>.log(sum(<span class="hljs-number">3</span>, <span class="hljs-number">7</span>));  
<span class="hljs-built_in">console</span>.log(multiply(<span class="hljs-number">3</span>, <span class="hljs-number">7</span>));
</code></pre>
<ul>
<li><strong>Importing all items of a module</strong></li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// main.js</span>

<span class="hljs-comment">// importing all items of a module</span>

<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> utils <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils.js'</span>;

<span class="hljs-built_in">console</span>.log(utils.sum(<span class="hljs-number">3</span>, <span class="hljs-number">7</span>));  
<span class="hljs-built_in">console</span>.log(utils.multiply(<span class="hljs-number">3</span>, <span class="hljs-number">7</span>));
</code></pre>
<h4 id="heading-imports-and-exports-can-be-aliased">Imports and Exports can be aliased</h4>
<p>If you want to avoid naming collisions, you can change the name of the exported object both during export as well as import. For example:</p>
<ul>
<li><strong>Renaming an export</strong></li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// utils.js</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params">num1, num2</span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Sum:'</span>, num1, num2);  
  <span class="hljs-keyword">return</span> num1 + num2;  
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiply</span>(<span class="hljs-params">num1, num2</span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Multiply:'</span>, num1, num2);  
  <span class="hljs-keyword">return</span> num1 \* num2;  
}

<span class="hljs-keyword">export</span> {sum <span class="hljs-keyword">as</span> add, multiply};
</code></pre>
<ul>
<li><strong>Renaming an import</strong></li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// main.js</span>

<span class="hljs-keyword">import</span> { add, multiply <span class="hljs-keyword">as</span> mult } <span class="hljs-keyword">from</span> <span class="hljs-string">'./utils.js'</span>;

<span class="hljs-built_in">console</span>.log(add(<span class="hljs-number">3</span>, <span class="hljs-number">7</span>));  
<span class="hljs-built_in">console</span>.log(mult(<span class="hljs-number">3</span>, <span class="hljs-number">7</span>));
</code></pre>
<h3 id="heading-singleton-pattern">Singleton Pattern</h3>
<p>A Singleton is an object which can be instantiated only once. A singleton pattern creates a new instance of a class if one doesn’t exist. If an instance exists, it simply returns a reference to that object. Any repeated calls to the constructor would always fetch the same object.</p>
<p>JavaScript has always had singletons built-in to the language. We just don’t call them singletons, we call them object literal. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> user = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Peter'</span>,  
  <span class="hljs-attr">age</span>: <span class="hljs-number">25</span>,  
  <span class="hljs-attr">job</span>: <span class="hljs-string">'Teacher'</span>,  
  <span class="hljs-attr">greet</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello!'</span>);  
  }  
};
</code></pre>
<p>Because each object in JavaScript occupies a unique memory location and when we call the <code>user</code> object, we are essentially returning a reference to this object.</p>
<p>If we try to copy the <code>user</code> variable into another variable and modify that variable. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> user1 = user;  
user1.name = <span class="hljs-string">'Mark'</span>;
</code></pre>
<p>We would see both objects are modified because objects in JavaScript are passed by reference, not by value. So there is only a single object in the memory. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// prints 'Mark'  </span>
<span class="hljs-built_in">console</span>.log(user.name);

<span class="hljs-comment">// prints 'Mark'  </span>
<span class="hljs-built_in">console</span>.log(user1.name);

<span class="hljs-comment">// prints true  </span>
<span class="hljs-built_in">console</span>.log(user === user1);
</code></pre>
<p>Singleton pattern can be implemented using the constructor function. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> instance = <span class="hljs-literal">null</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">User</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">if</span>(instance) {  
    <span class="hljs-keyword">return</span> instance;  
  }

  instance = <span class="hljs-built_in">this</span>;  
  <span class="hljs-built_in">this</span>.name = <span class="hljs-string">'Peter'</span>;  
  <span class="hljs-built_in">this</span>.age = <span class="hljs-number">25</span>;

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

<span class="hljs-keyword">const</span> user1 = <span class="hljs-keyword">new</span> User();  
<span class="hljs-keyword">const</span> user2 = <span class="hljs-keyword">new</span> User();

<span class="hljs-comment">// prints true  </span>
<span class="hljs-built_in">console</span>.log(user1 === user2);
</code></pre>
<p>When this constructor function is called, it checks if the <code>instance</code> object exists or not. If the object doesn’t exist, it assigns the <code>this</code> variable to the <code>instance</code> variable. And if the object exists, it just returns that object.</p>
<p>Singletons can also be implemented using the module pattern. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> singleton = (<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> instance;

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">init</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-keyword">return</span> {  
      <span class="hljs-attr">name</span>: <span class="hljs-string">'Peter'</span>,  
      <span class="hljs-attr">age</span>: <span class="hljs-number">24</span>,  
    };  
  }

  <span class="hljs-keyword">return</span> {  
    <span class="hljs-attr">getInstance</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
      <span class="hljs-keyword">if</span>(!instance) {  
        instance = init();  
      }
      <span class="hljs-keyword">return</span> instance;  
    }  
  }  
})();

<span class="hljs-keyword">const</span> instanceA = singleton.getInstance();  
<span class="hljs-keyword">const</span> instanceB = singleton.getInstance();

<span class="hljs-comment">// prints true  </span>
<span class="hljs-built_in">console</span>.log(instanceA === instanceB);
</code></pre>
<p>In the above code, we are creating a new instance by calling the <code>singleton.getInstance</code> method. If an instance already exists, this method simply returns that instance, if the instance doesn’t exist, it creates a new instance by calling the <code>init()</code> function.</p>
<h3 id="heading-factory-pattern">Factory Pattern</h3>
<p>Factory Pattern is a pattern that uses factory methods to create objects without specifying the exact class or constructor function from which the object will be created.</p>
<p>The factory pattern is used to create objects without exposing the instantiation logic. This pattern can be used when we need to generate a different object depending upon a specific condition. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span></span>{  
  <span class="hljs-keyword">constructor</span>(options) {  
    <span class="hljs-built_in">this</span>.doors = options.doors || <span class="hljs-number">4</span>;  
    <span class="hljs-built_in">this</span>.state = options.state || <span class="hljs-string">'brand new'</span>;  
    <span class="hljs-built_in">this</span>.color = options.color || <span class="hljs-string">'white'</span>;  
  }  
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Truck</span> </span>{  
  <span class="hljs-keyword">constructor</span>(options) {  
    <span class="hljs-built_in">this</span>.doors = options.doors || <span class="hljs-number">4</span>;  
    <span class="hljs-built_in">this</span>.state = options.state || <span class="hljs-string">'used'</span>;  
    <span class="hljs-built_in">this</span>.color = options.color || <span class="hljs-string">'black'</span>;  
  }  
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VehicleFactory</span> </span>{  
  createVehicle(options) {  
    <span class="hljs-keyword">if</span>(options.vehicleType === <span class="hljs-string">'car'</span>) {  
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Car(options);  
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(options.vehicleType === <span class="hljs-string">'truck'</span>) {  
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Truck(options);  
    }  
  }  
}
</code></pre>
<p>Here I have created a <code>Car</code> and a <code>Truck</code> class (with some default values) which is used to create new <code>car</code> and <code>truck</code> objects. And I have defined a <code>VehicleFactory</code> class to create and return a new object based on <code>vehicleType</code> property received in the <code>options</code> object.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> factory = <span class="hljs-keyword">new</span> VehicleFactory();

<span class="hljs-keyword">const</span> car = factory.createVehicle({  
  <span class="hljs-attr">vehicleType</span>: <span class="hljs-string">'car'</span>,  
  <span class="hljs-attr">doors</span>: <span class="hljs-number">4</span>,  
  <span class="hljs-attr">color</span>: <span class="hljs-string">'silver'</span>,  
  <span class="hljs-attr">state</span>: <span class="hljs-string">'Brand New'</span>  
});

<span class="hljs-keyword">const</span> truck= factory.createVehicle({  
  <span class="hljs-attr">vehicleType</span>: <span class="hljs-string">'truck'</span>,  
  <span class="hljs-attr">doors</span>: <span class="hljs-number">2</span>,  
  <span class="hljs-attr">color</span>: <span class="hljs-string">'white'</span>,  
  <span class="hljs-attr">state</span>: <span class="hljs-string">'used'</span>  
});

<span class="hljs-comment">// Prints Car {doors: 4, state: "Brand New", color: "silver"}  </span>
<span class="hljs-built_in">console</span>.log(car);

<span class="hljs-comment">// Prints Truck {doors: 2, state: "used", color: "white"}  </span>
<span class="hljs-built_in">console</span>.log(truck);
</code></pre>
<p>I have created a new object <code>factory</code> of <code>VehicleFactory</code> class. After that, we can create a new <code>Car</code> or <code>Truck</code> object by calling <code>factory.createVehicle</code> and passing an <code>options</code> object with a <code>vehicleType</code> property with a value of <code>car</code> or <code>truck</code>.</p>
<h3 id="heading-decorator-pattern">Decorator Pattern</h3>
<p>A Decorator pattern is used to extend the functionality of an object without modifying the existing class or constructor function. This pattern can be used to add features to an object without modifying the underlying code using them.</p>
<p>A simple example of this pattern would be:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Car</span>(<span class="hljs-params">name</span>) </span>{  
  <span class="hljs-built_in">this</span>.name = name;

  <span class="hljs-comment">// Default values  </span>
  <span class="hljs-built_in">this</span>.color = <span class="hljs-string">'White'</span>;  
}

<span class="hljs-comment">// Creating a new Object to decorate  </span>
<span class="hljs-keyword">const</span> tesla= <span class="hljs-keyword">new</span> Car(<span class="hljs-string">'Tesla Model 3'</span>);

<span class="hljs-comment">// Decorating the object with new functionality</span>
tesla.setColor = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">color</span>) </span>{  
  <span class="hljs-built_in">this</span>.color = color;  
}

tesla.setPrice = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">price</span>) </span>{  
  <span class="hljs-built_in">this</span>.price = price;  
}

tesla.setColor(<span class="hljs-string">'black'</span>);  
tesla.setPrice(<span class="hljs-number">49000</span>);

<span class="hljs-comment">// prints black  </span>
<span class="hljs-built_in">console</span>.log(tesla.color);
</code></pre>
<p>A more practical example of this pattern would be:</p>
<p>Let’s say, the cost of a car differs depending on the number of features it has. Without decorator pattern, we would have to create different classes for different combinations of features, each having a cost method to calculate the cost. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span>() </span>{  
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CarWithAC</span>() </span>{  
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CarWithAutoTransmission</span> </span>{  
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CarWithPowerLocks</span> </span>{  
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CarWithACandPowerLocks</span> </span>{  
}
</code></pre>
<p>But with decorator pattern, we can create a base class <code>Car</code> and add the cost of different configurations to its object using the decorator functions. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{  
  <span class="hljs-keyword">constructor</span>() {  
    <span class="hljs-comment">// Default Cost  </span>
    <span class="hljs-built_in">this</span>.cost = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
      <span class="hljs-keyword">return</span> <span class="hljs-number">20000</span>;  
    }  
  }  
}

<span class="hljs-comment">// Decorator function  </span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">carWithAC</span>(<span class="hljs-params">car</span>) </span>{  
  car.hasAC = <span class="hljs-literal">true</span>;  
  <span class="hljs-keyword">const</span> prevCost = car.cost();  
  car.cost = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-keyword">return</span> prevCost + <span class="hljs-number">500</span>;  
  }  
}

<span class="hljs-comment">// Decorator function  </span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">carWithAutoTransmission</span>(<span class="hljs-params">car</span>) </span>{  
  car.hasAutoTransmission = <span class="hljs-literal">true</span>;  
  <span class="hljs-keyword">const</span> prevCost = car.cost();  
  car.cost = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-keyword">return</span> prevCost + <span class="hljs-number">2000</span>;  
  }  
}

<span class="hljs-comment">// Decorator function  </span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">carWithPowerLocks</span>(<span class="hljs-params">car</span>) </span>{  
  car.hasPowerLocks = <span class="hljs-literal">true</span>;  
  <span class="hljs-keyword">const</span> prevCost = car.cost();  
  car.cost = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-keyword">return</span> prevCost + <span class="hljs-number">500</span>;  
  }  
}
</code></pre>
<p>First, we create a base class <code>Car</code> for creating the <code>Car</code> objects. Then, we create the decorator for the feature we want to add to it and pass the <code>Car</code> object as a parameter. Then we override the cost function of that object which returns the updated cost of the car and adds a new property to that object to indicate which feature has been added.</p>
<p>To add a new feature, we could do something like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> car = <span class="hljs-keyword">new</span> Car();  
<span class="hljs-built_in">console</span>.log(car.cost());

carWithAC(car);  
carWithAutoTransmission(car);  
carWithPowerLocks(car);
</code></pre>
<p>In the end, we can calculate the cost of the car like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Calculating total cost of the car  </span>
<span class="hljs-built_in">console</span>.log(car.cost());
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We have learned about various design patterns used in JavaScript, but there are many design patterns that I haven’t covered here, which can be implemented in JavaScript.</p>
<p>While it’s important to know various design patterns, it’s also equally important not to overuse them. Before using a design pattern, you should carefully consider if your problem fits that design pattern or not. To know if a pattern fits your problem, you should study the design pattern as well as the applications of that design pattern.</p>
<p>That’s it and if you found this article helpful, please click the like 🙂 button, you can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora">Hashnode</a>, <a target="_blank" href="https://medium.com/@sukhjinder">Medium</a> and <a target="_blank" href="https://twitter.com/_sukh_arora">Twitter</a>, and if you have any doubt, feel free to comment! I’d be happy to help :)</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Higher-Order Functions in JavaScript]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/understanding-higher-order-functions-in-javascript-75461803bad
If you are learning JavaScript, you must have come across the term Higher-Order Functions. Although it may sound complicat...]]></description><link>https://whatisweb.dev/understanding-higher-order-functions-in-javascript</link><guid isPermaLink="true">https://whatisweb.dev/understanding-higher-order-functions-in-javascript</guid><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Wed, 19 Oct 2022 14:33:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/IgUR1iX0mqM/upload/v1666180596301/18o1XJb7c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at: https://blog.bitsrc.io/understanding-higher-order-functions-in-javascript-75461803bad</em></strong></p>
<p>If you are learning JavaScript, you must have come across the term <em>Higher-Order Functions</em>. Although it may sound complicated, it isn’t.</p>
<p>What makes JavaScript suitable for functional programming is that it accepts Higher-Order Functions.</p>
<p>Higher-Order Functions are extensively used in JavaScript. If you have been programming in JavaScript for a while, you may have already used them without even knowing.</p>
<p>To fully understand this concept, you first have to understand what <em>Functional Programming</em> is and the concept of <em>First-Class Functions</em>.</p>
<h3 id="heading-what-is-functional-programming">What is Functional Programming</h3>
<p>In most simple terms, Functional Programming is a form of programming in which you can pass functions as parameters to other functions and also return them as values. In functional programming, we think and code in terms of functions.</p>
<p>JavaScript, Haskell, Clojure, Scala, and Erlang are some of the languages that implement functional programming.</p>
<h3 id="heading-first-class-functions">First-Class Functions</h3>
<p>If you have been learning JavaScript, you may have heard that JavaScript treats functions as first-class citizens. That’s because in JavaScript or any other functional programming language functions are objects.</p>
<p>In JavaScript, functions are a special type of object. They are <code>Function</code> objects. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greeting</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello World'</span>);  
}
<span class="hljs-comment">// Invoking the function  </span>
greeting();  <span class="hljs-comment">// prints 'Hello World</span>
</code></pre>
<p>To prove functions are objects in JavaScript, we could do something like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// We can add properties to functions as we do with objects  </span>
greeting.lang = <span class="hljs-string">'English'</span>;

<span class="hljs-comment">// Prints 'English'  </span>
<span class="hljs-built_in">console</span>.log(greeting.lang);
</code></pre>
<p><strong>Note —</strong> While this is perfectly valid in JavaScript, this is considered a harmful practice. You should not add random properties to the function objects, use an object if you have to.</p>
<p>In JavaScript, everything you can do with other types like objects, strings, or numbers, you can do with functions. You can pass them as parameters to other functions (callbacks), assign them to variables and pass them around, etc. This is why functions in JavaScript are known as First-Class Functions.</p>
<h4 id="heading-assigning-functions-to-variables">Assigning Functions to Variables</h4>
<p>We can assign functions to variables in JavaScript. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> square = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{  
  <span class="hljs-keyword">return</span> x * x;  
}

<span class="hljs-comment">// prints 25  </span>
square(<span class="hljs-number">5</span>);
</code></pre>
<p>We can also pass them around. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> foo = square;

<span class="hljs-comment">// prints 36  </span>
foo(<span class="hljs-number">6</span>);
</code></pre>
<h4 id="heading-passing-functions-as-parameters">Passing Functions as Parameters</h4>
<p>We can pass functions as parameters to other functions. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">formalGreeting</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"How are you?"</span>);  
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">casualGreeting</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"What's up?"</span>);  
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">type, greetFormal, greetCasual</span>) </span>{  
  <span class="hljs-keyword">if</span>(type === <span class="hljs-string">'formal'</span>) {  
    greetFormal();  
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(type === <span class="hljs-string">'casual'</span>) {  
    greetCasual();  
  }
}

<span class="hljs-comment">// prints 'What's up?'  </span>
greet(<span class="hljs-string">'casual'</span>, formalGreeting, casualGreeting);
</code></pre>
<p>Now that we know what first-class functions are, let’s dive into Higher-Order functions in JavaScript.</p>
<h3 id="heading-higher-order-functions">Higher-Order Functions</h3>
<p>Higher-order functions are functions that operate on other functions, either by taking them as arguments or by returning them. In simple words, A Higher-Order function is a function that receives a function as an argument or returns the function as output.</p>
<p>For example, <code>Array.prototype.map</code>, <code>Array.prototype.filter</code> and <code>Array.prototype.reduce</code> are some of the Higher-Order functions built into the language.</p>
<h4 id="heading-higher-order-functions-in-action">Higher-Order Functions in Action</h4>
<p>Let’s take a look at some examples of built-in higher-order functions and see how it compares to solutions where we aren’t using Higher-Order Functions.</p>
<h4 id="heading-arrayprototypemap">Array.prototype.map</h4>
<p>The <code>map()</code> method creates a new array by calling the callback function provided as an argument on every element in the input array. The <code>map()</code> method will take every returned value from the callback function and creates a new array using those values.</p>
<p>The callback function passed to the <code>map()</code> method accepts 3 arguments: <code>element</code>, <code>index</code>, and <code>array</code>.</p>
<p>Let’s look at some examples:</p>
<h4 id="heading-example-1"><strong>Example 1#</strong></h4>
<p>Let’s say we have an array of numbers and we want to create a new array where each item is double the values in the original array. Let’s see how we can solve this problem with and without Higher-Order Functions.</p>
<p><strong>Without Higher-order functions</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];  
<span class="hljs-keyword">const</span> arr2 = [];

<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; arr1.length; i++) {  
  arr2.push(arr1[i] * <span class="hljs-number">2</span>);  
}

<span class="hljs-comment">// prints [ 2, 4, 6 ]  </span>
<span class="hljs-built_in">console</span>.log(arr2);
</code></pre>
<p><strong>With Higher-order function</strong> <code>map</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];

<span class="hljs-keyword">const</span> arr2 = arr1.map(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">item</span>) </span>{  
  <span class="hljs-keyword">return</span> item * <span class="hljs-number">2</span>;  
});

<span class="hljs-built_in">console</span>.log(arr2);
</code></pre>
<p>We can make this even shorter using the arrow function syntax:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr1 = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];

<span class="hljs-keyword">const</span> arr2 = arr1.map(<span class="hljs-function"><span class="hljs-params">item</span> =&gt;</span> item * <span class="hljs-number">2</span>);

<span class="hljs-built_in">console</span>.log(arr2);
</code></pre>
<h4 id="heading-example-2"><strong>Example 2#</strong></h4>
<p>Let’s say we have an array containing the birth year of different persons and we want to create an array that contains their ages. For example:</p>
<p><strong>Without Higher-order function</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> birthYear = [<span class="hljs-number">1975</span>, <span class="hljs-number">1997</span>, <span class="hljs-number">2002</span>, <span class="hljs-number">1995</span>, <span class="hljs-number">1985</span>];  
<span class="hljs-keyword">const</span> ages = [];

<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; birthYear.length; i++) {  
  <span class="hljs-keyword">let</span> age = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getFullYear() - birthYear[i];  
  ages.push(age);  
}

<span class="hljs-comment">// prints [ 43, 21, 16, 23, 33 ]  </span>
<span class="hljs-built_in">console</span>.log(ages);
</code></pre>
<p><strong>With Higher-order function</strong> <code>map</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> birthYear = [<span class="hljs-number">1975</span>, <span class="hljs-number">1997</span>, <span class="hljs-number">2002</span>, <span class="hljs-number">1995</span>, <span class="hljs-number">1985</span>];

<span class="hljs-keyword">const</span> ages = birthYear.map(<span class="hljs-function"><span class="hljs-params">year</span> =&gt;</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getFullYear() - year);

<span class="hljs-comment">// prints [ 43, 21, 16, 23, 33 ]  </span>
<span class="hljs-built_in">console</span>.log(ages);
</code></pre>
<h4 id="heading-arrayprototypefilter">Array.prototype.filter</h4>
<p>The <code>filter()</code> method creates a new array with all elements that pass the test provided by the callback function. The callback function passed to the <code>filter()</code> method accepts 3 arguments: <code>element</code>, <code>index</code>, and <code>array</code>.</p>
<p>Let’s look at some examples:</p>
<h4 id="heading-example-1">Example 1</h4>
<p>Let’s say we have an array that contains objects with name and age properties. We want to create an array that contains only the persons with ages greater than or equal to 18.</p>
<p><strong>Without Higher-order function</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> persons = [  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'Peter'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">16</span> },  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'Mark'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">18</span> },  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">27</span> },  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'Jane'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">14</span> },  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'Tony'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">24</span>},  
];

<span class="hljs-keyword">const</span> adults = [];

<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; persons.length; i++) {  
  <span class="hljs-keyword">if</span>(persons[i].age &gt;= <span class="hljs-number">18</span>) {  
    adults.push(persons[i]);  
  }  
}

<span class="hljs-built_in">console</span>.log(adults);
</code></pre>
<p><strong>With Higher-order function</strong> <code>filter</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> persons = [  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'Peter'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">16</span> },  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'Mark'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">18</span> },  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'John'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">27</span> },  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'Jane'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">14</span> },  
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'Tony'</span>, <span class="hljs-attr">age</span>: <span class="hljs-number">24</span>},  
];

<span class="hljs-keyword">const</span> adults = persons.filter(<span class="hljs-function"><span class="hljs-params">person</span> =&gt;</span> person.age &gt;= <span class="hljs-number">18</span>);

<span class="hljs-built_in">console</span>.log(adults);
</code></pre>
<h4 id="heading-arrayprototypereduce">Array.prototype.reduce</h4>
<p>The <code>reduce</code> method executes the callback function on each member of the calling array which results in a single output value. The reduce method accepts two parameters: 1) The reducer function (callback), 2) and an optional <code>initialValue</code>.</p>
<p>The reducer function (callback) accepts four parameters: <code>accumulator</code>, <code>currentValue</code>, <code>currentIndex</code>, and <code>sourceArray</code>.</p>
<p>If an <code>initialValue</code> is provided, then the <code>accumulator</code> will be equal to the <code>initialValue</code> and the <code>currentValue</code> will be equal to the first element in the array.</p>
<p>If no <code>initialValue</code> is provided, then the <code>accumulator</code> will be equal to the first element in the array and the <code>currentValue</code> will be equal to the second element in the array.</p>
<h4 id="heading-example-1">Example 1</h4>
<p>Let’s say we have to sum an array of numbers:</p>
<p><strong>With Higher-order function</strong> <code>reduce</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">5</span>, <span class="hljs-number">7</span>, <span class="hljs-number">1</span>, <span class="hljs-number">8</span>, <span class="hljs-number">4</span>];

<span class="hljs-keyword">const</span> sum = arr.reduce(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">accumulator, currentValue</span>) </span>{  
  <span class="hljs-keyword">return</span> accumulator + currentValue;  
});

<span class="hljs-comment">// prints 25  </span>
<span class="hljs-built_in">console</span>.log(sum);
</code></pre>
<p>Every time the reducer function is called on each value in the array, the <code>accumulator</code> keeps the result of the previous operation returned from the reducer function, and the <code>currentValue</code> is set to the current item of the array. In the end, the result is stored in the <code>sum</code> variable.</p>
<p>We can also provide an initial value to this function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">5</span>, <span class="hljs-number">7</span>, <span class="hljs-number">1</span>, <span class="hljs-number">8</span>, <span class="hljs-number">4</span>];

<span class="hljs-keyword">const</span> sum = arr.reduce(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">accumulator, currentValue</span>) </span>{  
  <span class="hljs-keyword">return</span> accumulator + currentValue;  
}, <span class="hljs-number">10</span>);

<span class="hljs-comment">// prints 35  </span>
<span class="hljs-built_in">console</span>.log(sum);
</code></pre>
<p><strong>Without Higher-order function</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> arr = [<span class="hljs-number">5</span>, <span class="hljs-number">7</span>, <span class="hljs-number">1</span>, <span class="hljs-number">8</span>, <span class="hljs-number">4</span>];

<span class="hljs-keyword">let</span> sum = <span class="hljs-number">0</span>;

<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; arr.length; i++) {  
  sum = sum + arr[i];  
}

<span class="hljs-comment">// prints 25  </span>
<span class="hljs-built_in">console</span>.log(sum);
</code></pre>
<p>You can see that using the High-order functions made our code cleaner, more concise, and less verbose.</p>
<h3 id="heading-creating-our-own-higher-order-function">Creating Our own Higher-Order Function</h3>
<p>Up until this point, we saw various Higher-order functions built into the language. Now let’s create our own Higher-order function.</p>
<p>Let’s imagine JavaScript didn’t have the native map method. We could build it ourselves thus creating our own Higher-Order Function.</p>
<p>Let’s say, we have an array of strings and we want to convert this array to an array of integers, where each element represent the length of the string in the original array. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> stringArray = [<span class="hljs-string">'JavaScript'</span>, <span class="hljs-string">'Python'</span>, <span class="hljs-string">'PHP'</span>, <span class="hljs-string">'Java'</span>, <span class="hljs-string">'C'</span>];  

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">map</span>(<span class="hljs-params">arr, fn</span>) </span>{
  <span class="hljs-keyword">const</span> newArray = [];  
  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; arr.length; i++) {  
    newArray.push(  
      fn(arr[i])  
    );  
  }
  <span class="hljs-keyword">return</span> newArray;  
}

<span class="hljs-keyword">const</span> lengthArray = map(stringArray, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">item</span>) </span>{  
  <span class="hljs-keyword">return</span> item.length;  
});

<span class="hljs-comment">// prints [ 10, 6, 3, 4, 1 ]  </span>
<span class="hljs-built_in">console</span>.log(lengthArray);
</code></pre>
<p>In the above example, we created a Higher-order function <code>map</code> which accepts an array and a callback function <code>fn</code>. This function loops over the provided array and calls the callback function <code>fn</code> inside the <code>newArray.push</code> function call on each iteration.</p>
<p>The callback function <code>fn</code> receives the current element of the array and returns the length of that element, which is stored inside the <code>newArray</code>. After the <code>for</code> loop has finished, the <code>newArray</code> is returned and assigned to the <code>lengthArray</code>.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We have learned what Higher-order functions are and saw some of the built-in Higher-order functions in JavaScript. We also learned how to create our own Higher-order functions.</p>
<p>In a nutshell, a Higher-order function is a function that may receive a function as an argument and can even return a function. Higher-order functions are just like regular functions with the added ability to receive other functions as arguments and return them as output.</p>
<p>That’s it and if you found this article helpful, please click the like 🙂 button, you can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora">Hashnode</a>, <a target="_blank" href="https://medium.com/@sukhjinder">Medium</a> and <a target="_blank" href="https://twitter.com/_sukh_arora">Twitter</a>, and if you have any doubt, feel free to comment! I’d be happy to help :)</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Scope and Scope Chain in JavaScript]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/understanding-scope-and-scope-chain-in-javascript-f6637978cf53
Scope and Scope Chain are fundamental concepts of JavaScript and other programming languages. Yet, these concepts confuse ...]]></description><link>https://whatisweb.dev/understanding-scope-and-scope-chain-in-javascript</link><guid isPermaLink="true">https://whatisweb.dev/understanding-scope-and-scope-chain-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Mon, 17 Oct 2022 17:10:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/BVr3XaBiWLU/upload/v1666023567272/h4IkVBY26.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at: https://blog.bitsrc.io/understanding-scope-and-scope-chain-in-javascript-f6637978cf53</em></strong></p>
<p>Scope and Scope Chain are fundamental concepts of JavaScript and other programming languages. Yet, these concepts confuse many new JavaScript developers. The knowledge of these concepts is essential in mastering JavaScript.</p>
<p>Having a proper understanding of these concepts will help you to write better, more efficient and clean code. Which will, in turn, help you to become a better JavaScript developer.</p>
<p>So in this article, I will explain what scope and scope chain is, how JavaScript engine performs variable lookups and internals of these concepts.</p>
<p>So without further ado, Let’s get started :)</p>
<h3 id="heading-what-is-scope">What is Scope?</h3>
<p>Scope in JavaScript refers to the accessibility or visibility of variables. That is, which parts of a program have access to the variable or where the variable is visible.</p>
<h4 id="heading-why-is-scope-important">Why is Scope Important?</h4>
<ol>
<li>The main benefit of scope is security. That is, the variables can be accessed from only a certain area of the program. Using scope, we can avoid unintended modifications to the variables from other parts of the program.</li>
<li>The scope also reduces the namespace collisions. That is, we can use the same variable names in different scopes.</li>
</ol>
<h3 id="heading-types-of-scope">Types of Scope</h3>
<p>There are three types of scope in JavaScript — 1) <strong>Global Scope,</strong> 2) <strong>Function Scope,</strong> and, 3) <strong>Block Scope.</strong></p>
<h4 id="heading-1-global-scope">1. Global Scope</h4>
<p>Any variable that’s not inside any function or block (a pair of curly braces), is inside the global scope. The variables in global scope can be accessed from anywhere in the program. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> greeting = <span class="hljs-string">'Hello World!'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(greeting);  
}

<span class="hljs-comment">// Prints 'Hello World!'  </span>
greet();
</code></pre>
<h4 id="heading-2-local-scope-or-function-scope">2. Local Scope or Function Scope</h4>
<p>Variables declared inside a function is inside the local scope. They can only be accessed from within that function, that means they can’t be accessed from the outside code. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">var</span> greeting = <span class="hljs-string">'Hello World!'</span>;  
  <span class="hljs-built_in">console</span>.log(greeting);  
}

<span class="hljs-comment">// Prints 'Hello World!'  </span>
greet();

<span class="hljs-comment">// Uncaught ReferenceError: greeting is not defined  </span>
<span class="hljs-built_in">console</span>.log(greeting);
</code></pre>
<h4 id="heading-3-block-scope">3. Block Scope</h4>
<p>ES6 introduced <strong>let</strong> and <strong>const</strong> variables, unlike <strong>var</strong> variables, they can be scoped to the nearest pair of curly braces. That means, they can’t be accessed from outside that pair of curly braces. For example:</p>
<pre><code class="lang-javascript">{  
  <span class="hljs-keyword">let</span> greeting = <span class="hljs-string">'Hello World!'</span>;  
  <span class="hljs-keyword">var</span> lang = <span class="hljs-string">'English'</span>;  
  <span class="hljs-built_in">console</span>.log(greeting); <span class="hljs-comment">// Prints 'Hello World!'  </span>
}

<span class="hljs-comment">// Prints 'English'  </span>
<span class="hljs-built_in">console</span>.log(lang);

<span class="hljs-comment">// Uncaught ReferenceError: greeting is not defined  </span>
<span class="hljs-built_in">console</span>.log(greeting);
</code></pre>
<p>We can see that <code>var</code> variables can be used outside the block, that is, <code>var</code> variables are not block scoped.</p>
<h3 id="heading-nested-scope">Nested Scope</h3>
<p>Just like functions in JavaScript, a scope can be nested inside another scope. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> name = <span class="hljs-string">'Peter'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">var</span> greeting = <span class="hljs-string">'Hello'</span>;  
  {  
    <span class="hljs-keyword">let</span> lang = <span class="hljs-string">'English'</span>;  
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${lang}</span>: <span class="hljs-subst">${greeting}</span> <span class="hljs-subst">${name}</span>`</span>);  
  }  
}

greet();
</code></pre>
<p>Here we have 3 scopes nested within each other. First, the block scope (created due to the <code>let</code> variable) is nested inside the local or function scope which is in turn nested inside the global scope.</p>
<h3 id="heading-lexical-scope">Lexical Scope</h3>
<p>Lexical Scope (also known as Static Scope) literally means that scope is determined at the <a target="_blank" href="https://en.wikipedia.org/wiki/Lexical_analysis">lexing time</a> (generally referred to as compiling) rather than at runtime. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> number = <span class="hljs-number">42</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printNumber</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(number);  
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">log</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> number = <span class="hljs-number">54</span>;  
  printNumber();  
}

<span class="hljs-comment">// Prints 42  </span>
log();
</code></pre>
<p>Here the <code>console.log(number)</code> will always print <code>42</code> no matter from where the function <code>printNumber()</code> is called. This is different from languages with the <strong>dynamic scope</strong> where the <code>console.log(number)</code> will print different value depending on from where the function <code>printNumber()</code> is called.</p>
<p>If the above code was written in a language that supports dynamic scoping, the <code>console.log(number)</code> would have printed <code>54</code> instead.</p>
<p>Using lexical scope we can determine the scope of the variable just by looking at the source code. Whereas in the case of dynamic scoping the scope can’t be determined until the code is executed.</p>
<p>Most of the programming languages support lexical or static scope such as C, C++, Java, JavaScript. Perl supports both static and dynamic scoping.</p>
<h3 id="heading-scope-chain">Scope Chain</h3>
<p>When a variable is used in JavaScript, the JavaScript engine will try to find the variable’s value in the current scope. If it could not find the variable, it will look into the outer scope and will continue to do so until it finds the variable or reaches global scope.</p>
<p>If it’s still could not find the variable, it will either implicitly declare the variable in the global scope (if not in strict mode) or return an error.</p>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> foo = <span class="hljs-string">'foo'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bar</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> baz = <span class="hljs-string">'baz'</span>;

  <span class="hljs-comment">// Prints 'baz'  </span>
  <span class="hljs-built_in">console</span>.log(baz);

  <span class="hljs-comment">// Prints 'foo'  </span>
  <span class="hljs-built_in">console</span>.log(foo);

  number = <span class="hljs-number">42</span>;  
  <span class="hljs-built_in">console</span>.log(number);  <span class="hljs-comment">// Prints 42  </span>
}

bar();
</code></pre>
<p>When the function <code>bar()</code> is executed, the JavaScript engine looks for the <code>baz</code> variable and finds it in the current scope. Next, it looks for <code>foo</code> variable in the current scope and it can’t find it there, so it looks for the variable in outer scope and finds it there (i.e global scope).</p>
<p>After that, we assign <code>42</code> to the number variable, so the JavaScript engine looks for the <code>number</code> variable in the current scope and after that in the outer scope.</p>
<p>If the script is not in strict mode, the engine will create a new variable named <code>number</code> and assign <code>42</code> to it or return an error (if not in strict mode).</p>
<p>So when a variable is used the engine will traverse the scope chain until it finds the variable.</p>
<h3 id="heading-how-does-scope-and-scope-chain-work">How Does Scope and Scope Chain Work?</h3>
<p>Up until now, we have discussed what scope is and types of scope. Now let’s understand how JavaScript engine determines the scope of variables and perform variable lookups under the hood.</p>
<p>In order to understand how JavaScript engine performs variable lookups, we have to understand the concept of lexical environment in JavaScript.</p>
<h4 id="heading-what-is-a-lexical-environment">What is a Lexical Environment?</h4>
<p>A <em>lexical environment</em> is a structure that holds <strong>identifier-variable mapping</strong>. (here <strong>identifier</strong> refers to the name of variables/functions, and the <strong>variable</strong> is the reference to actual object [including function object and array object] or primitive value).</p>
<p>Simply put, a lexical environment is a place where variables and references to the objects are stored.</p>
<p><strong>Note —</strong> Don’t confuse lexical scope with the lexical environment, lexical scope is a scope that is determined at compile time and a lexical environment is a place where variables are stored during the program execution.</p>
<p>Conceptually a lexical environment looks like this:</p>
<pre><code class="lang-text">lexicalEnvironment = {  
  a: 25,  
  obj: &lt;ref. to the object&gt;  
}
</code></pre>
<p>A new lexical environment is created for each lexical scope but only when the code in that scope is executed. The lexical environment also has a reference to its outer lexical environment ( i.e outer scope). For example:</p>
<pre><code class="lang-text">lexicalEnvironment = {  
  a: 25,  
  obj: &lt;ref. to the object&gt;

  outer: &lt;outer lexical environemt&gt;  
}
</code></pre>
<h4 id="heading-how-does-javascript-engine-perform-variable-lookups">How does JavaScript Engine Perform Variable Lookups?</h4>
<p>Now that we know what scope, scope chain and lexical environment are, let’s now understand how JavaScript engine uses the lexical environment to determine scope and scope chain.</p>
<p>Let’s take a look at below code snippet to understand the above concepts.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> greeting = <span class="hljs-string">'Hello'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> name = <span class="hljs-string">'Peter'</span>;  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${greeting}</span> <span class="hljs-subst">${name}</span>`</span>);  
}

greet();

{  
  <span class="hljs-keyword">let</span> greeting = <span class="hljs-string">'Hello World!'</span>  
  <span class="hljs-built_in">console</span>.log(greeting);  
}
</code></pre>
<p>When the above script loads, a global lexical environment is created, which contains variables and functions defined inside the global scope. For example:</p>
<pre><code class="lang-text">globalLexicalEnvironment = {  
  greeting: 'Hello'  
  greet: &lt;ref. to greet function&gt;

  outer: &lt;null&gt;  
}
</code></pre>
<p>Here outer lexical environment is set to null because there is no outer scope after global scope.</p>
<p>After that, a call to the <code>greet()</code> function is encountered. So a new lexical environment is created for the <code>greet()</code> function. For example:</p>
<pre><code class="lang-text">functionLexicalEnvironment = {  
  name: 'Peter'

  outer: &lt;globalLexicalEnvironment&gt;  
}
</code></pre>
<p>Here outer lexical environment is set to <code>globalLexicalEnvironment</code> because its outer scope is the global scope.</p>
<p>After that, the JavaScript engine executes the <code>console.log(`${greeting} ${name}`)</code> statement.</p>
<p>The JavaScript engine tries to find the <code>greeting</code> and <code>name</code> variables inside the function’s lexical environment. It finds the <code>name</code> variable inside the current lexical environment but it won’t be able to find the <code>greeting</code> variable inside the current lexical environment.</p>
<p>So it looks inside the outer lexical environment (defined by the outer property i.e global lexical environment) and finds the <code>greeting</code> variable.</p>
<p>Next, the JavaScript engine executes at the code inside the block. So it creates a new lexical environment for that block. For example:</p>
<pre><code class="lang-text">blockLexicalEnvironment = {  
  greeting: 'Hello World',

  outer: &lt;globalLexicalEnvironment&gt;  
}
</code></pre>
<p>Next, the <code>console.log(greeting)</code> statement is executed, the JavaScript engine finds the variable in the current lexical environment and uses that variable. So it does not look inside the outer lexical environment (global lexical environment) for the variable.</p>
<p><strong>Note —</strong> A new lexical environment is created only for <code>let</code> and <code>const</code> declarations, not <code>var</code> declarations. <code>var</code> declarations are added to the current lexical environment (global or function lexical environment).</p>
<p>So when a variable is used in a program, the JavaScript engine will try to find the variable in the current lexical environment and if it could not find the variable there, it looks inside the outer lexical environment to find the variable. So that’s how the JavaScript engine performs variable lookups.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>So in a nutshell, a scope is an area where a variable is visible and accessible. Just like functions, scopes in JavaScript can be nested and the JavaScript engine traverses the scope chain to find the variables used in the program.</p>
<p>JavaScript uses lexical scope which means that scope of variables is determined at compile time. The JavaScript engine uses the lexical environment to store the variables during the program execution.</p>
<p>Scope and scope chain are fundamental concepts of JavaScript that every JavaScript developer should understand. Having a good knowledge of these concepts will help you to become a much more effective and better JavaScript developer.</p>
<p>That’s it and if you found this article helpful, please click the like 🙂 button, you can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora">Hashnode</a>, <a target="_blank" href="https://medium.com/@sukhjinder">Medium</a> and <a target="_blank" href="https://twitter.com/_sukh_arora">Twitter</a>, and if you have any doubt, feel free to comment! I’d be happy to help :)</p>
]]></content:encoded></item><item><title><![CDATA[Hoisting in Modern JavaScript — let, const, and var]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/hoisting-in-modern-javascript-let-const-and-var-b290405adfda
Many JavaScript programmers explain hoisting as JavaScript’s behavior of moving declarations (variable and function) to the ...]]></description><link>https://whatisweb.dev/hoisting-in-modern-javascript-let-const-and-var</link><guid isPermaLink="true">https://whatisweb.dev/hoisting-in-modern-javascript-let-const-and-var</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Sat, 15 Oct 2022 11:53:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/vw3Ahg4x1tY/upload/v1665662407953/V9p2QjZ6P.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at: https://blog.bitsrc.io/hoisting-in-modern-javascript-let-const-and-var-b290405adfda</em></strong></p>
<p>Many JavaScript programmers explain hoisting as <em>JavaScript’s behavior of moving declarations (variable and function) to the top of their current scope (function or global).</em> As if they were physically moved to the top of your code, which is not the case. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(a);
<span class="hljs-keyword">var</span> a= <span class="hljs-string">'Hello World!'</span>;
</code></pre>
<p>They will say, the above code will transform into this code after hoisting:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> a;
<span class="hljs-built_in">console</span>.log(a);
a = <span class="hljs-string">'Hello World!'</span>;
</code></pre>
<p>Although this is what appears to be happening (because the code is working fine), this isn’t actually happening, your code isn’t going anywhere. The JavaScript engine is not physically moving your code, your code stays where you typed it.</p>
<h3 id="heading-so-what-is-hoisting-then">So What is Hoisting Then?</h3>
<p>During compile phase, just microseconds before your code is executed, it is scanned for function and variable declarations. All these functions and variable declarations are added to the memory inside a JavaScript data structure called <strong>Lexical Environment</strong>. So that they can be used even before they are actually declared in the source code.</p>
<h4 id="heading-what-is-a-lexical-environment">What is a Lexical Environment?</h4>
<p>A <em>lexical environment</em> is a data structure that holds <strong>identifier-variable mapping</strong>. (here <strong>identifier</strong> refers to the name of variables/functions, and <strong>the variable</strong> is the reference to actual object [including function object] or primitive value).</p>
<p>This is what a lexical environment conceptually look like:</p>
<pre><code class="lang-text">LexicalEnvironment = {
  Identifier:  &lt;value&gt;,
  Identifier:  &lt;function object&gt;
}
</code></pre>
<p>So in short, a <em>lexical environment</em> is a place where variables and functions live during the program execution.</p>
<p><em>If you want to know more about lexical environments, you can read my previous article</em> <a target="_blank" href="https://whatisweb.dev/understanding-execution-context-and-execution-stack-in-javascript"><em>here</em></a><em>.</em></p>
<p>Now that we know what hoisting actually is, let’s take a look at how hoisting happens for function and variable (<code>var</code>, <code>let</code> and <code>const</code>) declarations.</p>
<h4 id="heading-hoisting-function-declaration">Hoisting Function Declaration:</h4>
<pre><code class="lang-javascript">helloWorld();  <span class="hljs-comment">// prints 'Hello World!' to the console</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">helloWorld</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello World!'</span>);
}
</code></pre>
<p>As we already know that function declarations are added to the memory during the compile stage, so we are able to access it in our code before the actual function declaration.</p>
<p>So the lexical environment for the above code will look something like this:</p>
<pre><code class="lang-text">lexicalEnvironment = {
  helloWorld: &lt; func &gt;
}
</code></pre>
<p>So when the JavaScript engine encounters a call to <code>helloWorld()</code>, it will look into the lexical environment, finds the function and will be able to execute it.</p>
<h4 id="heading-hoisting-function-expressions">Hoisting Function Expressions</h4>
<p>Only function declarations are hoisted in JavaScript, function expressions are not hoisted. For example: this code won’t work.</p>
<pre><code class="lang-javascript">helloWorld();  <span class="hljs-comment">// TypeError: helloWorld is not a function</span>
<span class="hljs-keyword">var</span> helloWorld = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello World!'</span>);
}
</code></pre>
<p>As JavaScript only hoist declarations, not initializations (assignments), so the <code>helloWorld</code> will be treated as a variable, not as a function. Because <code>helloWorld</code> is a <code>var</code> variable, so the engine will assign is the <code>undefined</code> value during hoisting.</p>
<p>So this code will work.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> helloWorld = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello World!'</span>);  prints <span class="hljs-string">'Hello World!'</span>
}
helloWorld();
</code></pre>
<h4 id="heading-hoisting-var-variables">Hoisting var variables:</h4>
<p>Let’s look at some examples to understand hoisting in case of <code>var</code> variables.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(a); <span class="hljs-comment">// outputs 'undefined'  </span>
<span class="hljs-keyword">var</span> a = <span class="hljs-number">3</span>;
</code></pre>
<p>We expected <code>3</code> but instead got <code>undefined</code>. Why?</p>
<p>Remember JavaScript only hoist declarations, not initializations<em>.</em> That is, during compile time, JavaScript only stores function and variable declarations in the memory, not their assignments (value).</p>
<p><strong>But why</strong> <code>**undefined**</code><strong>?</strong></p>
<p>When JavaScript engine finds a <code>var</code> variable declaration during the compile phase, it will add that variable to the lexical environment and initialize it with <code>undefined</code> and later during the execution when it reaches the line where the actual assignment is done in the code, it will assign that value to the variable.</p>
<p>So the initial lexical environment for the above code will look something like this:</p>
<pre><code class="lang-text">lexicalEnvironment = {
  a: undefined
}
</code></pre>
<p>That’s why we got <code>undefined</code> instead of <code>3</code>. And when the engine reaches the line (during execution) where the actual assignment is done, it will update the value of the variable in its lexical environment. So the lexical environment after the assignment will look like this:</p>
<pre><code class="lang-text">lexicalEnvironment = {  
  a: 3  
}
</code></pre>
<h4 id="heading-hoisting-let-and-const-variables">Hoisting let and const variables:</h4>
<p>Let’s first take a look at some examples:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(a);  
<span class="hljs-keyword">let</span> a = <span class="hljs-number">3</span>;
</code></pre>
<p>Output:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">ReferenceError</span>: a is not defined
</code></pre>
<p>So are <code>let</code> and <code>const</code> variables not hoisted?</p>
<p>The answer is a bit more complicated than that. All declarations (function, var, let, const and class) are hoisted in JavaScript, while the <code>var</code> declarations are initialized with <code>undefined</code>, but <code>let</code> and <code>const</code> declarations remain uninitialized.</p>
<p>They will only get initialized when their lexical binding (assignment) is evaluated during runtime by the JavaScript engine. This means you can’t access the variable before the engine evaluates its value at the place it was declared in the source code. This is what we call “<strong>Temporal Dead Zone</strong>”, A time span between variable creation and its initialization where they can’t be accessed.</p>
<p>If the JavaScript engine still can’t find the value of <code>let</code> or <code>const</code> variables at the line where they were declared, it will assign them the value of <code>undefined</code> or return an error (in case of <code>const</code>).</p>
<p>Let’s look at some more example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> a;  
<span class="hljs-built_in">console</span>.log(a); <span class="hljs-comment">// outputs undefined  </span>
a = <span class="hljs-number">5</span>;
</code></pre>
<p>Here during the compile phase, the JavaScript engine encounters the variable <code>a</code> and stores it in the lexical environment, but because it’s a <code>let</code> variable, the engine does not initialize it with any value. So during the compile phase, the lexical environment will look like this:</p>
<pre><code class="lang-text">lexicalEnvironment = {  
  a: &lt;uninitialized&gt;  
}
</code></pre>
<p>Now if we try to access the variable before it is declared, the JavaScript engine will try to fetch the value of the variable from the lexical environment, because the variable is uninitialized, it will throw a reference error.</p>
<p>During the execution, when the engine reaches the line where the variable was declared, it will try to evaluate its binding (value), because the variable has no value associated with it, it will assign it <code>undefined</code>.</p>
<p>So the lexical environment will look like this after execution of the first line:</p>
<pre><code class="lang-text">lexicalEnvironment = {  
  a: undefined  
}
</code></pre>
<p>And <code>undefined</code> will be logged to the console and after that <code>5</code> will be assigned to it and the lexical environment will be updated to contain the value of <code>a</code> to <code>5</code> from <code>undefined</code>.</p>
<p><strong>Note —</strong> We can reference the <code>let</code> and <code>const</code> variables in the code (eg. function body ) even before they are declared, as long as that code is not executed before the variable declaration.</p>
<p>For example, This code is perfectly valid.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo</span> (<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(a);  
}

<span class="hljs-keyword">let</span> a = <span class="hljs-number">20</span>;  
foo();  <span class="hljs-comment">// This is perfectly valid</span>
</code></pre>
<p>But this will generate a reference error.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo</span>(<span class="hljs-params"></span>) </span>{  
 <span class="hljs-built_in">console</span>.log(a); <span class="hljs-comment">// ReferenceError: a is not defined  </span>
}  
foo(); <span class="hljs-comment">// This is not valid  </span>
<span class="hljs-keyword">let</span> a = <span class="hljs-number">20</span>;
</code></pre>
<h4 id="heading-hoisting-class-declaration">Hoisting Class Declaration</h4>
<p>Just as <code>let</code> and <code>const</code> declarations, classes in JavaScript are also hoisted, and just as <code>let</code> or <code>const</code> declarations, they remain uninitialized until evaluation. So they are also affected by the “Temporal Dead Zone”. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> peter = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">'Peter'</span>, <span class="hljs-number">25</span>); <span class="hljs-comment">// ReferenceError: Person is not defined  </span>
<span class="hljs-built_in">console</span>.log(peter);

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{  
  <span class="hljs-keyword">constructor</span>(name, age) {  
    <span class="hljs-built_in">this</span>.name = name;  
    <span class="hljs-built_in">this</span>.age = age;  
  }  
}
</code></pre>
<p>So to access the classes, you have to declare them first. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{  
  <span class="hljs-keyword">constructor</span>(name, age) {  
    <span class="hljs-built_in">this</span>.name = name;  
    <span class="hljs-built_in">this</span>.age = age;  
  }  
}

<span class="hljs-keyword">let</span> peter = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">'Peter'</span>, <span class="hljs-number">25</span>);   
<span class="hljs-built_in">console</span>.log(peter);  
<span class="hljs-comment">// Person { name: 'Peter', age: 25 }</span>
</code></pre>
<p>So again during the compile phase, the lexical environment for the above code will look like this:</p>
<pre><code class="lang-text">lexicalEnvironment = {  
  Person: &lt;uninitialized&gt;  
}
</code></pre>
<p>And when the engine has evaluated the class statement, it will initialize the class with the value.</p>
<pre><code class="lang-text">lexicalEnvironment = {  
  Person: &lt;Person object&gt;  
}
</code></pre>
<h4 id="heading-hoisting-class-expressions">Hoisting Class Expressions</h4>
<p>Just as function expressions, class expressions are also not hoisted. For example, this code won’t work.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> peter = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">'Peter'</span>, <span class="hljs-number">25</span>); <span class="hljs-comment">// ReferenceError: Person is not defined  </span>
<span class="hljs-built_in">console</span>.log(peter);

<span class="hljs-keyword">let</span> Person = <span class="hljs-class"><span class="hljs-keyword">class</span> </span>{  
  <span class="hljs-keyword">constructor</span>(name, age) {  
    <span class="hljs-built_in">this</span>.name = name;  
    <span class="hljs-built_in">this</span>.age = age;  
  }  
}
</code></pre>
<p>The correct way to do it is like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> Person = <span class="hljs-class"><span class="hljs-keyword">class</span> </span>{  
  <span class="hljs-keyword">constructor</span>(name, age) {  
    <span class="hljs-built_in">this</span>.name = name;  
    <span class="hljs-built_in">this</span>.age = age;  
  }  
}

<span class="hljs-keyword">let</span> peter = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">'Peter'</span>, <span class="hljs-number">25</span>);   
<span class="hljs-built_in">console</span>.log(peter);  
<span class="hljs-comment">// Person { name: 'Peter', age: 25 }</span>
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>So now we know that during hoisting our code is not physically moved by the JavaScript engine. Having a proper understanding of the hoisting mechanism will help you avoid any future bugs and confusion arising due to hoisting. To avoid possible side effects of hoisting like undefined variables or reference error, always try to declare the variables at the top of their respective scopes and also always try to initialize variables when you declare them.</p>
<p>That’s it and if you found this article helpful, please click the like 🙂 button, you can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora">Hashnode</a>, <a target="_blank" href="https://medium.com/@sukhjinder">Medium</a> and <a target="_blank" href="https://twitter.com/_sukh_arora">Twitter</a>, and if you have any doubt, feel free to comment! I’d be happy to help :)</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Execution Context and Execution Stack in Javascript]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/understanding-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0
If you are or want to be a JavaScript developer, then you must know how the JavaScript programs are execut...]]></description><link>https://whatisweb.dev/understanding-execution-context-and-execution-stack-in-javascript</link><guid isPermaLink="true">https://whatisweb.dev/understanding-execution-context-and-execution-stack-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Sat, 15 Oct 2022 11:16:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/i25aqE_YUZs/upload/v1665835061205/4QeewYWa8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at: https://blog.bitsrc.io/understanding-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0</em></strong></p>
<p>If you are or want to be a JavaScript developer, then you must know how the JavaScript programs are executed internally. The understanding of execution context and execution stack is vital in order to understand other JavaScript concepts such as Hoisting, Scope, and Closures.</p>
<p>Properly understanding the concept of execution context and execution stack will make you a much better JavaScript developer.</p>
<p>So without further ado, let’s get started :)</p>
<h3 id="heading-what-is-an-execution-context">What is an Execution Context?</h3>
<p>Simply put, an execution context is an abstract concept of an environment where the Javascript code is evaluated and executed. Whenever any code is run in JavaScript, it’s run inside an execution context.</p>
<h4 id="heading-types-of-execution-context">Types of Execution Context</h4>
<p>There are three types of execution context in JavaScript.</p>
<ul>
<li><strong>Global Execution Context —</strong> This is the default or base execution context. The code that is not inside any function is in the global execution context. It performs two things: it creates a global object which is a window object (in the case of browsers) and sets the value of <code>this</code> to equal to the global object. There can only be one global execution context in a program.</li>
<li><strong>Functional Execution Context —</strong> Every time a function is invoked, a brand new execution context is created for that function. Each function has its own execution context, but it’s created when the function is invoked or called. There can be any number of function execution contexts. Whenever a new execution context is created, it goes through a series of steps in a defined order which I will discuss later in this article.</li>
<li><strong>Eval Function Execution Context —</strong> Code executed inside an <code>eval</code> function also gets its own execution context, but as <code>eval</code> isn’t usually used by JavaScript developers, so I will not discuss it here.</li>
</ul>
<h3 id="heading-execution-stack">Execution Stack</h3>
<p>Execution stack, also known as “calling stack” in other programming languages, is a stack with a LIFO (Last in, First out) structure, which is used to store all the execution context created during the code execution.</p>
<p>When the JavaScript engine first encounters your script, it creates a global execution context and pushes it to the current execution stack. Whenever the engine finds a function invocation, it creates a new execution context for that function and pushes it to the top of the stack.</p>
<p>The engine executes the function whose execution context is at the top of the stack. When this function completes, its execution stack is popped off from the stack, and the control reaches to the context below it in the current stack.</p>
<p>Let’s understand this with a code example below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> a = <span class="hljs-string">'Hello World!'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">first</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Inside first function'</span>);  
  second();  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Again inside first function'</span>);  
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">second</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Inside second function'</span>);  
}

first();  
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Inside Global Execution Context'</span>);
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198460063/wf09HlkKMC.png" alt /></p>
<p>When the above code loads in the browser, the JavaScript engine creates a global execution context and pushes it to the current execution stack. When a call to <code>first()</code> is encountered, the JavaScript engines creates a new execution context for that function and pushes it to the top of the current execution stack.</p>
<p>When the <code>second()</code> function is called from within the <code>first()</code> function, the Javascript engine creates a new execution context for that function and pushes it to the top of the current execution stack. When the <code>second()</code> function finishes, its execution context is popped off from the current stack, and the control reaches to the execution context below it, that is the <code>first()</code> function execution context.</p>
<p>When the <code>first()</code> finishes, its execution stack is removed from the stack and control reaches to the global execution context. Once all the code is executed, the JavaScript engine removes the global execution context from the current stack.</p>
<h3 id="heading-how-is-the-execution-context-created">How is the Execution Context created?</h3>
<p>Up until now, we have seen how the JavaScript engine manages the execution context, Now let’s understand how an execution context is created by the JavaScript engine.</p>
<p>The execution context is created in two phases: <strong>1) Creation Phase</strong> and <strong>2) Execution Phase.</strong></p>
<h3 id="heading-the-creation-phase">The Creation Phase</h3>
<p>The execution context is created during the creation phase. Following things happen during the creation phase:</p>
<ol>
<li><strong>LexicalEnvironment</strong> component is created.</li>
<li><strong>VariableEnvironment</strong> component is created.</li>
</ol>
<p>So the execution context can be conceptually represented as follows:</p>
<pre><code class="lang-text">ExecutionContext = {  
  LexicalEnvironment = &lt;ref. to LexicalEnvironment in memory&gt;,  
  VariableEnvironment = &lt;ref. to VariableEnvironment in  memory&gt;,  
}
</code></pre>
<h4 id="heading-lexical-environment">Lexical Environment</h4>
<p>The <a target="_blank" href="http://ecma-international.org/ecma-262/6.0/">official ES6</a> docs define Lexical Environment as</p>
<blockquote>
<p>A <em>Lexical Environment</em> is a specification type used to define the association of <em>Identifiers</em> to specific variables and functions based upon the lexical nesting structure of ECMAScript code. A Lexical Environment consists of an Environment Record and a possibly null reference to an <em>outer</em> Lexical Environment.</p>
</blockquote>
<p>Simply put, A <em>lexical environment</em> is a structure that holds <strong>identifier-variable mapping</strong>. (here <strong>identifier</strong> refers to the name of variables/functions, and the <strong>variable</strong> is the reference to actual object [including function object and array object] or primitive value).</p>
<p>For example, consider the following snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> a = <span class="hljs-number">20</span>;  
<span class="hljs-keyword">var</span> b = <span class="hljs-number">40</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'bar'</span>);  
}
</code></pre>
<p>So the lexical environment for the above snippet looks like this:</p>
<pre><code class="lang-text">lexicalEnvironment = {  
  a: 20,  
  b: 40,  
  foo: &lt;ref. to foo function&gt;  
}
</code></pre>
<p>Each Lexical Environment has three components:</p>
<ol>
<li>Environment Record</li>
<li>Reference to the outer environment,</li>
<li>This binding.</li>
</ol>
<h4 id="heading-environment-record"><strong>Environment Record</strong></h4>
<p>The environment record is the place where the variable and function declarations are stored inside the lexical environment.</p>
<p>There are also two types of <em>environment record</em> :</p>
<ul>
<li><strong>Declarative environment record —</strong> As its name suggests stores variable and function declarations. The lexical environment for function code contains a declarative environment record.</li>
<li><strong>Object environment record —</strong> The lexical environment for global code contains a objective environment record. Apart from variable and function declarations, the object environment record also stores a global binding object (window object in browsers). So for each of binding object’s property (in case of browsers, it contains properties and methods provided by browser to the window object), a new entry is created in the record.</li>
</ul>
<p><strong>Note —</strong> For the <strong>function code</strong>, the <em>environment record</em> also contains an <code>arguments</code> object that contains the mapping between indexes and arguments passed to the function and the <em>length(number)</em> of the arguments passed into the function. For example, an argument object for the below function looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">foo</span>(<span class="hljs-params">a, b</span>) </span>{  
  <span class="hljs-keyword">var</span> c = a + b;  
}  
foo(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>);

<span class="hljs-comment">// argument object  </span>
Arguments: {<span class="hljs-number">0</span>: <span class="hljs-number">2</span>, <span class="hljs-number">1</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">length</span>: <span class="hljs-number">2</span>},
</code></pre>
<h4 id="heading-reference-to-the-outer-environment">Reference to the Outer Environment</h4>
<p>The <strong>reference to the outer environment</strong> means it has access to its outer lexical environment. That means that the JavaScript engine can look for variables inside the outer environment if they are not found in the current lexical environment.</p>
<h4 id="heading-this-binding">This Binding</h4>
<p>In this component, the value of <code>this</code> is determined or set.</p>
<p>In the global execution context, the value of <code>this</code> refers to the global object. (in browsers, <code>this</code> refers to the Window Object).</p>
<p>In the function execution context, the value of <code>this</code> depends on how the function is called. If it is called by an object reference, then the value of <code>this</code> is set to that object, otherwise, the value of <code>this</code> is set to the global object or <code>undefined</code>(in strict mode). For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> person = {  
  <span class="hljs-attr">name</span>: <span class="hljs-string">'peter'</span>,  
  <span class="hljs-attr">birthYear</span>: <span class="hljs-number">1994</span>,  
  <span class="hljs-attr">calcAge</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-built_in">console</span>.log(<span class="hljs-number">2018</span> - <span class="hljs-built_in">this</span>.birthYear);  
  }  
}

person.calcAge();   
<span class="hljs-comment">// 'this' refers to 'person', because 'calcAge' was called with //'person' object reference</span>

<span class="hljs-keyword">const</span> calculateAge = person.calcAge;  
calculateAge();  
<span class="hljs-comment">// 'this' refers to the global window object, because no object reference was given</span>
</code></pre>
<p>Abstractly, the lexical environment looks like this in pseudocode:</p>
<pre><code class="lang-text">GlobalExectionContext = {
    LexicalEnvironment: {
        EnvironmentRecord: {
            Type: "Object",
            // Identifier bindings go here
        }
        outer: &lt; null &gt; ,
        this: &lt; global object &gt;
    }
}
FunctionExectionContext = {
    LexicalEnvironment: {
        EnvironmentRecord: {
            Type: "Declarative",
            // Identifier bindings go here
        }
        outer: &lt; Global or outer
        function environment reference &gt; ,
        this: &lt; depends on how
        function is called &gt;
    }
}
</code></pre>
<h4 id="heading-variable-environment">Variable Environment:</h4>
<p>It’s also a Lexical Environment whose EnvironmentRecord holds bindings created by <em>VariableStatements</em> within this execution context.</p>
<p>As written above, the variable environment is also a lexical environment, So it has all the properties and components of a lexical environment as defined above.</p>
<p>In ES6, one difference between <strong>LexicalEnvironment</strong> component and the <strong>VariableEnvironment</strong> component is that the former is used to store function declaration and variable (<code>let</code> and <code>const</code>) bindings, while the latter is used to store the variable <code>(var)</code> bindings only.</p>
<h3 id="heading-execution-phase">Execution Phase</h3>
<p>In this phase assignments to all those variables are done and the code is finally executed.</p>
<h3 id="heading-example">Example</h3>
<p>Let’s look at some example to understand the above concepts:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> a = <span class="hljs-number">20</span>;  
<span class="hljs-keyword">const</span> b = <span class="hljs-number">30</span>;  
<span class="hljs-keyword">var</span> c;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multiply</span>(<span class="hljs-params">e, f</span>) </span>{  
 <span class="hljs-keyword">var</span> g = <span class="hljs-number">20</span>;  
 <span class="hljs-keyword">return</span> e \* f \* g;  
}

c = multiply(<span class="hljs-number">20</span>, <span class="hljs-number">30</span>);
</code></pre>
<p>When the above code is executed, the JavaScript engine creates a global execution context to execute the global code. So the global execution context will look something like this during the creation phase:</p>
<pre><code class="lang-text">GlobalExectionContext = {
    LexicalEnvironment: {
        EnvironmentRecord: {
            Type: "Object",
            // Identifier bindings go here  
            a: &lt; uninitialized &gt; ,
            b: &lt; uninitialized &gt; ,
            multiply: &lt; func &gt;
        }
        outer: &lt; null &gt; ,
        ThisBinding: &lt; Global Object &gt;
    },
    VariableEnvironment: {
        EnvironmentRecord: {
            Type: "Object",
            // Identifier bindings go here  
            c: undefined,
        }
        outer: &lt; null &gt; ,
        ThisBinding: &lt; Global Object &gt;
    }
}
</code></pre>
<p>During the execution phase, the variable assignments are done. So the global execution context will look something like this during the execution phase.</p>
<pre><code class="lang-text">GlobalExectionContext = {
    LexicalEnvironment: {
        EnvironmentRecord: {
            Type: "Object",
            // Identifier bindings go here  
            a: 20,
            b: 30,
            multiply: &lt; func &gt;
        }
        outer: &lt; null &gt; ,
        ThisBinding: &lt; Global Object &gt;
    },
    VariableEnvironment: {
        EnvironmentRecord: {
            Type: "Object",
            // Identifier bindings go here  
            c: undefined,
        }
        outer: &lt; null &gt; ,
        ThisBinding: &lt; Global Object &gt;
    }
}
</code></pre>
<p>When a call to function <code>multiply(20, 30)</code> is encountered, a new function execution context is created to execute the function code. So the function execution context will look something like this during the creation phase:</p>
<pre><code class="lang-text">FunctionExectionContext = {
    LexicalEnvironment: {
        EnvironmentRecord: {
            Type: "Declarative",
            // Identifier bindings go here  
            Arguments: {
                0: 20,
                1: 30,
                length: 2
            },
        },
        outer: &lt; GlobalLexicalEnvironment &gt; ,
        ThisBinding: &lt; Global Object or undefined &gt; ,
    },
    VariableEnvironment: {
        EnvironmentRecord: {
            Type: "Declarative",
            // Identifier bindings go here  
            g: undefined
        },
        outer: &lt; GlobalLexicalEnvironment &gt; ,
        ThisBinding: &lt; Global Object or undefined &gt;
    }
}
</code></pre>
<p>After this, the execution context goes through the execution phase that means assignments to the variables inside the function are done. So the function execution context will look something like this during the execution phase:</p>
<pre><code class="lang-text">FunctionExectionContext = {
    LexicalEnvironment: {
        EnvironmentRecord: {
            Type: "Declarative",
            // Identifier bindings go here  
            Arguments: {
                0: 20,
                1: 30,
                length: 2
            },
        },
        outer: &lt; GlobalLexicalEnvironment &gt; ,
        ThisBinding: &lt; Global Object or undefined &gt; ,
    },
    VariableEnvironment: {
        EnvironmentRecord: {
            Type: "Declarative",
            // Identifier bindings go here  
            g: 20
        },
        outer: &lt; GlobalLexicalEnvironment &gt; ,
        ThisBinding: &lt; Global Object or undefined &gt;
    }
}
</code></pre>
<p>After the function completes, the returned value is stored inside <code>c</code>. So the global lexical environment is updated. After that, the global code completes and the program finishes.</p>
<p><strong>Note —</strong> As you might have noticed that the <code>let</code> and <code>const</code> defined variables do not have any value associated with them during the creation phase, but <code>var</code> defined variables are set to <code>undefined</code> .</p>
<p>This is because, during the creation phase, the code is scanned for variable and function declarations, while the function declaration is stored in its entirety in the environment, the variables are initially set to <code>undefined</code> (in case of <code>var</code>) or remain uninitialized (in case of <code>let</code> and <code>const</code>).</p>
<p>This is the reason why you can access <code>var</code> defined variables before they are declared (though <code>undefined</code>) but get a reference error when accessing <code>let</code> and <code>const</code> variables before they are declared.</p>
<p>This is, what we call hoisting.</p>
<p><strong>Note —</strong> During the execution phase, if the JavaScript engine couldn’t find the value of <code>let</code> variable at the actual place it was declared in the source code, then it will assign it the value of <code>undefined</code>.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>So we have discussed how JavaScript programs are executed internally. While it’s not necessary that you learn all these concepts to be an awesome JavaScript developer, having a decent understanding of the above concepts will help you to understand other concepts such as Hoisting, Scope, and Closures more easily and deeply.</p>
<p>That’s it and if you found this article helpful, please click the like 🙂 button, you can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora">Hashnode</a>, <a target="_blank" href="https://medium.com/@sukhjinder">Medium</a> and <a target="_blank" href="https://twitter.com/_sukh_arora">Twitter</a>, and if you have any doubt, feel free to comment! I’d be happy to help :)</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Sass: CSS Made Awesome]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/the-complete-beginners-guide-to-sass-ee8d5278f4c
While CSS is getting more powerful day by day, it still lacks certain features (such as code reuse) that make it harder to maintain when...]]></description><link>https://whatisweb.dev/the-complete-beginners-guide-to-sass</link><guid isPermaLink="true">https://whatisweb.dev/the-complete-beginners-guide-to-sass</guid><category><![CDATA[CSS]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[Sass]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Wed, 12 Oct 2022 17:33:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/_yMciiStJyY/upload/v1665593894832/0ozFKuhOB.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at: https://blog.bitsrc.io/the-complete-beginners-guide-to-sass-ee8d5278f4c</em></strong></p>
<p>While CSS is getting more powerful day by day, it still lacks certain features (such as code reuse) that make it harder to maintain when the projects get bigger and more complex.</p>
<p>There are many CSS methodologies (such as OOCSS, and SMACSS) that help us write more maintainable CSS code, but these methodologies alone aren’t enough to solve the problem of maintaining large CSS codebases.</p>
<p>That’s where Sass comes into play. Sass provides us with features and tools that regular CSS doesn’t have, using Sass we can write more readable, maintainable, and reusable CSS code.</p>
<p>So in this article, I will dive into what Sass is, how to compile Sass code into regular CSS, and discuss features that make it so powerful.</p>
<p>So without further ado, let’s get started :)</p>
<h3 id="heading-what-is-sass">What is Sass?</h3>
<p>If you know CSS or if you are learning CSS, then you must have heard about Sass. Sass is a <strong>CSS preprocessor</strong>, a superset of CSS that adds features that aren’t available in regular CSS.</p>
<p>A <strong>CSS preprocessor</strong> is a language that extends CSS, adds features to CSS, and gets compiled into regular CSS. A CSS preprocessor helps developers to write cleaner and easier-to-understand CSS code.</p>
<p>Some well known CSS preprocessors are: <strong>SASS</strong>, <strong>LESS</strong>, and <strong>Stylus</strong>.</p>
<h4 id="heading-sass-or-scss">Sass or SCSS?</h4>
<p>There are two syntaxes available for Sass. 1) <strong>SCSS</strong> and 2) <strong>Sass</strong></p>
<ol>
<li>SCSS known as Sassy CSS is a newer and most-used version of Sass. It has a similar syntax to CSS because it’s a language extension or a superset of CSS. So a valid CSS is also a valid SCSS. Its file extension is <code>.scss</code>.</li>
<li>Sass is an older syntax of Sass. It uses indentation rather than brackets. Its file extension is <code>.sass</code>.</li>
</ol>
<p>In this article, I will use the SCSS syntax of Sass.</p>
<h3 id="heading-installing-sass">Installing Sass</h3>
<p>Browsers do not understand Sass, for browsers to understand the Sass code we write, we have to convert it into regular CSS code. We do this by running the Sass compiler which converts our Sass code to into regular CSS code.</p>
<h4 id="heading-getting-started">Getting Started:</h4>
<p>Before starting, you must have npm installed on your computer, which comes bundled with <a target="_blank" href="https://nodejs.org/en/">Node.js</a>, you can install it from <a target="_blank" href="https://nodejs.org/en/download/">here</a>.</p>
<h4 id="heading-folder-structure">Folder Structure:</h4>
<p>Let’s first create the below folder in which we will install Sass.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198570285/XbELm0kSY.png" alt /></p>
<p>You can create the above directories with these commands.</p>
<pre><code class="lang-bash">mkdir sass-demo  
<span class="hljs-built_in">cd</span> sass-demo  
mkdir -p sass css
</code></pre>
<h4 id="heading-initialize-the-project-directory">Initialize the Project Directory:</h4>
<p>All projects that use the node package manager(npm) must be initialized. To initialize the project enter the below command in a terminal. This will create a <strong>package.json</strong> file.</p>
<pre><code class="lang-bash">npm init -y
</code></pre>
<h4 id="heading-installing-sass">Installing sass</h4>
<p>The <code>sass</code> package is the JavaScript implementation of the sass. This command will install sass as a dependency of our project.</p>
<pre><code class="lang-bash">npm install sass
</code></pre>
<h4 id="heading-compiling-sass-code-to-css">Compiling Sass Code to CSS</h4>
<p>Create an npm script to compile the Sass code into CSS code. Add this script inside the script section of the <strong>package.json</strong> file.</p>
<pre><code class="lang-json"><span class="hljs-string">"compile-sass"</span>: <span class="hljs-string">"sass sass/main.scss css/style.css"</span>
</code></pre>
<p>Here <code>main.scss</code> is our main Sass file, and <code>style.css</code> is the compiled CSS file.</p>
<p>We can also add a <code>--watch</code> flag. The <code>watch</code> flag tells the Sass compiler to watch your source files for changes, and re-compile CSS each time you save your Sass files. For example:</p>
<pre><code class="lang-json"><span class="hljs-string">"compile-sass"</span>: <span class="hljs-string">"sass sass/main.scss css/style.css --watch"</span>
</code></pre>
<p>Finally, we can compile our Sass code into CSS by running the below command in the terminal.</p>
<pre><code class="lang-bash">npm run compile-sass
</code></pre>
<h3 id="heading-sass-features">Sass Features</h3>
<p>Now that we know what Sass is, and how to install Sass, let’s dive into various features of Sass that make it so powerful.</p>
<h3 id="heading-1-variables">1# Variables</h3>
<p>Variables are one of the most useful features of Sass. Variables allow us to define certain values and reuse them across the code. Variables in Sass are similar to variables in JavaScript. In Sass, variables always start with a <code>$</code>.</p>
<p>For example:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$variable-name</span>: variable-value;
</code></pre>
<p>Let’s take a look at the below HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"heading"</span>&gt;</span>  
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"heading-primary"</span>&gt;</span>This is a primary heading<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>  
  <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"heading-secondary"</span>&gt;</span>This is a secondary heading<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Let’s define two variables for primary and secondary colors:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$color-primary</span>: <span class="hljs-number">#55c57a</span>;  
<span class="hljs-variable">$color-secondary</span>: <span class="hljs-number">#7ed56f</span>;
</code></pre>
<p>Let’s style the above headings in Sass:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.heading-primary</span> {  
  <span class="hljs-attribute">color</span>: <span class="hljs-variable">$color-primary</span>;  
  <span class="hljs-attribute">text-align</span>: center;  
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;  
}

<span class="hljs-selector-class">.heading-secondary</span> {  
  <span class="hljs-attribute">color</span>: <span class="hljs-variable">$color-secondary</span>;  
  <span class="hljs-attribute">text-align</span>: center;  
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">15px</span>;  
}
</code></pre>
<p>The above code will be compiled into below CSS code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.heading-primary</span> {  
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#55c57a</span>;  
  <span class="hljs-attribute">text-align</span>: center;  
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;  
}

<span class="hljs-selector-class">.heading-secondary</span> {  
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#7ed56f</span>;  
  <span class="hljs-attribute">text-align</span>: center;  
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">15px</span>;  
}
</code></pre>
<p>After compiling, the variables will be replaced by their actual values in CSS.</p>
<h3 id="heading-2-nesting">2# Nesting</h3>
<p>Nesting is another useful feature of Sass. CSS doesn’t support selector nesting. Using nesting, we can nest child selectors inside the parent selector.</p>
<p>For example, consider the below HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navigation"</span>&gt;</span>  
  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>  
  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
</code></pre>
<p>Without Sass, we’d have to write the following CSS code:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.navigation</span> {  
  <span class="hljs-attribute">background-color</span>: yellow;  
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;  
}

<span class="hljs-selector-class">.navigation</span> <span class="hljs-selector-tag">ul</span> {  
  <span class="hljs-attribute">list-style</span>: none;  
}

<span class="hljs-selector-class">.navigation</span> <span class="hljs-selector-tag">li</span> {  
  <span class="hljs-attribute">text-align</span>: center;  
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">20px</span>;  
}
</code></pre>
<p>Notice that we have to repeat the <code>navigation</code> class name every time we want to style its children. With Sass, we can write cleaner and less repetitive code. For example:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.navigation</span> {  
  <span class="hljs-attribute">background-color</span>: yellow;  
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;

  <span class="hljs-selector-tag">ul</span> {  
    <span class="hljs-attribute">list-style</span>: none;  
  }

  <span class="hljs-selector-tag">li</span> {  
    <span class="hljs-attribute">text-align</span>: center;  
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">20px</span>;  
  }  
}
</code></pre>
<h3 id="heading-3-mixins">3# Mixins</h3>
<p>Mixins are yet another powerful feature of Sass. Using mixins, we can reduce code redundancy and increase code reuse. A mixin is a reusable piece of code that is similar to functions. For example, we can define a mixin as follows:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@mixin</span> mixin_name() {  
  <span class="hljs-comment">/* code */</span>  
}
</code></pre>
<p>Let’s take a look at the below HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"box"</span>&gt;</span>  
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>  
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>  
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Sass code:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.box</span> {  
  <span class="hljs-attribute">background-color</span>: red;  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;  
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;  
  <span class="hljs-attribute">position</span>: relative;  

  <span class="hljs-selector-tag">div</span> {  
    <span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;  
    <span class="hljs-attribute">height</span>: <span class="hljs-number">200px</span>;  
    <span class="hljs-attribute">background-color</span>: blue;  
    <span class="hljs-attribute">position</span>: absolute;  
    <span class="hljs-attribute">top</span>: <span class="hljs-number">50%</span>;  
    <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;  
    <span class="hljs-attribute">transform</span>: translate(-<span class="hljs-number">50%</span>, -<span class="hljs-number">50%</span>);  
  }  
}
</code></pre>
<p>Here we are positioning the inner div at the center of the outer div. We can place the code inside a mixin called <code>absCenterPosition</code>. For example:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@mixin</span> absCenterPosition() {  
  <span class="hljs-attribute">position</span>: absolute;  
  <span class="hljs-attribute">top</span>: <span class="hljs-number">50%</span>;  
  <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;  
  <span class="hljs-attribute">transform</span>: translate(-<span class="hljs-number">50%</span>, -<span class="hljs-number">50%</span>);  
}
</code></pre>
<p>We can include the above mixin in our code by using the <code>@include</code> directive, for example:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.box</span> {  
  <span class="hljs-attribute">background-color</span>: red;  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;  
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;  
  <span class="hljs-attribute">position</span>: relative;  

  <span class="hljs-selector-tag">div</span> {  
    <span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;  
    <span class="hljs-attribute">height</span>: <span class="hljs-number">200px</span>;  
    <span class="hljs-attribute">background-color</span>: blue;  
    <span class="hljs-keyword">@include</span> absCenterPosition;  
  }  
}
</code></pre>
<p>We can also pass arguments to the mixins. For example:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@mixin</span> box-shadow(<span class="hljs-variable">$x</span>, <span class="hljs-variable">$y</span>, <span class="hljs-variable">$blur</span>, <span class="hljs-variable">$spread</span>) {  
  -webkit-<span class="hljs-attribute">box-shadow</span>: <span class="hljs-variable">$x</span> <span class="hljs-variable">$y</span> <span class="hljs-variable">$blur</span> <span class="hljs-variable">$spread</span>;  
  -moz-<span class="hljs-attribute">box-shadow</span>: <span class="hljs-variable">$x</span> <span class="hljs-variable">$y</span> <span class="hljs-variable">$blur</span> <span class="hljs-variable">$spread</span>;  
  -ms-<span class="hljs-attribute">box-shadow</span>: <span class="hljs-variable">$x</span> <span class="hljs-variable">$y</span> <span class="hljs-variable">$blur</span> <span class="hljs-variable">$spread</span>;  
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-variable">$x</span> <span class="hljs-variable">$y</span> <span class="hljs-variable">$blur</span> <span class="hljs-variable">$spread</span>;  
}
</code></pre>
<p>We can include the mixin as:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.box</span> {  
  <span class="hljs-attribute">background-color</span>: red;  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;  
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;  
  <span class="hljs-attribute">position</span>: relative;  

  <span class="hljs-selector-tag">div</span> {  
    <span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;  
    <span class="hljs-attribute">height</span>: <span class="hljs-number">200px</span>;  
    <span class="hljs-attribute">background-color</span>: blue;  
    <span class="hljs-keyword">@include</span> absCenterPosition;  
    <span class="hljs-keyword">@include</span> box-shadow(<span class="hljs-number">0</span>, <span class="hljs-number">5px</span>, <span class="hljs-number">5px</span>, rgba(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.7</span>));  
  }  
}
</code></pre>
<h3 id="heading-4-functions">4# Functions</h3>
<p>Functions in Sass are similar to functions in JavaScript. Just like JavaScript, functions in Sass can accept arguments and return some value. For example:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@function</span> divide(<span class="hljs-variable">$a</span>, <span class="hljs-variable">$b</span>) {  
  <span class="hljs-keyword">@return</span> <span class="hljs-variable">$a</span> / <span class="hljs-variable">$b</span>;  
}

<span class="hljs-selector-tag">div</span> {  
  <span class="hljs-attribute">margin</span>: divide(<span class="hljs-number">60</span>, <span class="hljs-number">2</span>) \* <span class="hljs-number">1px</span>;  
  <span class="hljs-attribute">height</span>: <span class="hljs-number">200px</span>;  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;  
}
</code></pre>
<h3 id="heading-5-partials-and-import">5# Partials and Import</h3>
<p>Partials in Sass are separate files containing Sass code that make our code modular. Using partials, we can have separate Sass files for different components.</p>
<p>A partial’s name always starts with an underscore(<code>_</code>). We use an <code>@import</code> directive to import partial into another Sass file. For example, we can import the <code>_header.scss</code> file into <code>main.scss</code> file.</p>
<pre><code class="lang-scss"><span class="hljs-comment">// main.scss  </span>
<span class="hljs-keyword">@import</span> <span class="hljs-string">'header'</span>;
</code></pre>
<p><em>When importing a partial, we can omit the underscore(</em><code>*_*</code><em>) and</em> <code>*.scss*</code> <em>file extension.</em></p>
<p>Unlike CSS imports, Sass imports don’t send another HTTP request for fetching the partial, because during compiling all the imports are placed in a single CSS file.</p>
<h3 id="heading-7-inheritanceextend">#7 Inheritance/Extend</h3>
<p>In Sass, we can extend CSS properties from one selector to another. For this, we use the <code>@extend</code> directive.</p>
<p>Generally, for the inheritance we use placeholder classes that start with a <code>%</code>, the advantage of using placeholder classes is that they only print in compiled CSS when it is extended and can help keep your compiled CSS neat and clean.</p>
<p>For example:</p>
<pre><code class="lang-scss">%panel {  
  <span class="hljs-attribute">background-color</span>: blue;  
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid red;  
}

<span class="hljs-selector-class">.small-panel</span> {  
  <span class="hljs-keyword">@extend</span> %panel;  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">70px</span>;  
  <span class="hljs-attribute">height</span>: <span class="hljs-number">70px</span>;  
}

<span class="hljs-selector-class">.big-panel</span> {  
  <span class="hljs-keyword">@extend</span> %panel;  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;  
  <span class="hljs-attribute">height</span>: <span class="hljs-number">200px</span>;  
}
</code></pre>
<p>This will be compiled into the following CSS.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.small-panel</span>,  
<span class="hljs-selector-class">.big-panel</span> {  
  <span class="hljs-attribute">background-color</span>: blue;  
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid red;  
}

<span class="hljs-selector-class">.small-panel</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">70px</span>;  
  <span class="hljs-attribute">height</span>: <span class="hljs-number">70px</span>;  
}

<span class="hljs-selector-class">.big-panel</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">200px</span>;  
  <span class="hljs-attribute">height</span>: <span class="hljs-number">200px</span>;  
}
</code></pre>
<h3 id="heading-6-ampersand-andamp-operator">6# Ampersand (&amp;) operator</h3>
<p>The ampersand (&amp;) operator is another useful feature of Sass. This operator is particularly useful when you are using <a target="_blank" href="https://css-tricks.com/bem-101/">BEM</a> methodology.</p>
<p>Let’s take a look at the below HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn--green"</span>&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>If we have to style it without the <code>&amp;</code> operator, we’d do something like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.btn</span> {  
  <span class="hljs-attribute">display</span>: inline-block;  
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">5px</span> <span class="hljs-number">8px</span>;  
}

<span class="hljs-selector-class">.btn--green</span> {  
  <span class="hljs-attribute">background-color</span>: green;  
}

<span class="hljs-selector-class">.btn</span><span class="hljs-selector-pseudo">:hover</span> {  
  <span class="hljs-attribute">background-color</span>: transparent;  
}
</code></pre>
<p>But using the <code>&amp;</code> operator we can do it like this:</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.btn</span> {  
  <span class="hljs-attribute">display</span>: inline-block;  
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">5px</span> <span class="hljs-number">8px</span>;

  &amp;--green {  
    <span class="hljs-attribute">background-color</span>: green;  
  }

  &amp;<span class="hljs-selector-pseudo">:hover</span> {  
    <span class="hljs-attribute">background-color</span>: transparent;  
  }  
}
</code></pre>
<p>So using the <code>&amp;</code> operator, we can nest selectors that share the same name, and during compile time the <code>&amp;</code> operator will be replaced by its enclosing selector name.</p>
<h3 id="heading-5-directives">5# Directives</h3>
<p>There are many directives in Sass. For example, <code>@extend</code>, <code>@mixin</code>, and <code>@import</code> are some of the directives that we have seen above. There are many more directives in Sass, such as <code>@if</code>, <code>@else</code>, <code>@for</code>, and <code>@while</code>.</p>
<h4 id="heading-if-and-else-directives"><code>@if</code> and <code>@else</code> directives</h4>
<p>The <code>@if</code> and <code>@else</code> directives are similar to if and else statements in JavaScript. For example:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@mixin</span> text-color(<span class="hljs-variable">$val</span>) {  
  <span class="hljs-keyword">@if</span> <span class="hljs-variable">$val</span> == error {  
    <span class="hljs-attribute">color</span>: red;  
  }  
  <span class="hljs-keyword">@else</span> if <span class="hljs-variable">$val</span> == warning {  
    <span class="hljs-attribute">color</span>: yellow;  
  }  
  <span class="hljs-keyword">@else</span> if <span class="hljs-variable">$val</span> == success {  
    <span class="hljs-attribute">color</span>: green;  
  }  
  <span class="hljs-keyword">@else</span> {  
    <span class="hljs-attribute">color</span>: black  
  }  
}

.heading {  
  @include text-color(error);  
}
</code></pre>
<p>Here, we are using a mixin <code>text-color</code> which accepts an argument <code>$val</code>. We can have a different color for the heading depending on the value passed to the mixin.</p>
<h4 id="heading-for-and-while-directive"><code>@for</code> and <code>@while</code> directive</h4>
<p>The <code>@for</code> and <code>@while</code> directives are similar to for and while loops in JavaScript. For example:</p>
<pre><code class="lang-scss"><span class="hljs-keyword">@for</span> <span class="hljs-variable">$i</span> from <span class="hljs-number">1</span> through <span class="hljs-number">4</span>{  
  <span class="hljs-selector-class">.col-</span>#{<span class="hljs-variable">$i</span>} {  
     <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span> / <span class="hljs-variable">$i</span>;  
  }  
}
</code></pre>
<p>We use <code>#{}</code> to use variables inside a selector name and other CSS functions. This will be compiled into the following CSS.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.col-1</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;   
}

<span class="hljs-selector-class">.col-2</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">50%</span>;   
}

<span class="hljs-selector-class">.col-3</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">33.33333%</span>;   
}

<span class="hljs-selector-class">.col-4</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">25%</span>;   
}
</code></pre>
<p>We can also implement the above code using the <code>@while</code> directive. For example:</p>
<pre><code class="lang-scss"><span class="hljs-variable">$i</span>: <span class="hljs-number">1</span>;  
<span class="hljs-keyword">@while</span> <span class="hljs-variable">$i</span> &lt; <span class="hljs-number">5</span> {  
  <span class="hljs-selector-class">.col-</span>#{<span class="hljs-variable">$i</span>} {  
     <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span> / <span class="hljs-variable">$i</span>;  
  }  
  <span class="hljs-variable">$i</span>: <span class="hljs-variable">$i</span> + <span class="hljs-number">1</span>;  
}
</code></pre>
<p>This will be compiled into the following CSS:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.col-1</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;   
}

<span class="hljs-selector-class">.col-2</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">50%</span>;   
}

<span class="hljs-selector-class">.col-3</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">33.33333%</span>;   
}

<span class="hljs-selector-class">.col-4</span> {  
  <span class="hljs-attribute">width</span>: <span class="hljs-number">25%</span>;   
}
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>We have learned what Sass is, how to install it locally, and discussed the features that make it so powerful. Sass adds basic programming capabilities to CSS. Using Sass, we can perform basic calculations, reuse code using mixins, and create functions. Sass makes maintenance of CSS so much easier in bigger projects.</p>
<p>That’s it and if you found this article helpful, please click the like 😀 button, you can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora">Hashnode</a>, <a target="_blank" href="https://medium.com/@Sukhjinder">Medium</a> and <a target="_blank" href="https://twitter.com/_sukh_arora">Twitter</a>, and if you have any doubt, feel free to comment! I’d be happy to help :)</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Closures in JavaScript]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/a-beginners-guide-to-closures-in-javascript-97d372284dda
Closures are a fundamental concept of JavaScript that every JavaScript developer should know and understand. Yet, it’s a concept...]]></description><link>https://whatisweb.dev/a-beginners-guide-to-closures-in-javascript</link><guid isPermaLink="true">https://whatisweb.dev/a-beginners-guide-to-closures-in-javascript</guid><category><![CDATA[javascript framework]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[closure]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Wed, 12 Oct 2022 16:46:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/mDinBvq1Sfg/upload/v1665503671615/bBCh-Niz3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at: https://blog.bitsrc.io/a-beginners-guide-to-closures-in-javascript-97d372284dda</em></strong></p>
<p>Closures are a fundamental concept of JavaScript that every JavaScript developer should know and understand. Yet, it’s a concept that confuses many new JavaScript developers.</p>
<p>Having a proper understanding of closures will help you write better, more efficient, and clean code. Which will, in turn, help you to become a better JavaScript developer.</p>
<p>So in this article, I will try to explain the internals of closures and how they really work in JavaScript.</p>
<p>So without further ado, Let’s get started :)</p>
<h3 id="heading-what-is-closure">What is Closure?</h3>
<p>A closure is a function that has access to its outer function scope even after the outer function has returned. This means a closure can remember and access variables and arguments of its outer function even after the function has finished.</p>
<p>Before we dive into closures, let’s first understand the lexical scope.</p>
<h4 id="heading-what-is-a-lexical-scope">What is a Lexical Scope?</h4>
<p>A lexical scope or static scope in JavaScript refers to the accessibility of the variables, functions, and objects based on their physical location in the source code. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> a = <span class="hljs-string">'global'</span>;

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">outer</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-keyword">let</span> b = <span class="hljs-string">'outer'</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">inner</span>(<span class="hljs-params"></span>) </span>{  
      <span class="hljs-keyword">let</span> c = <span class="hljs-string">'inner'</span>  
      <span class="hljs-built_in">console</span>.log(c);   <span class="hljs-comment">// prints 'inner'  </span>
      <span class="hljs-built_in">console</span>.log(b);   <span class="hljs-comment">// prints 'outer'  </span>
      <span class="hljs-built_in">console</span>.log(a);   <span class="hljs-comment">// prints 'global'  </span>
    }  
    <span class="hljs-built_in">console</span>.log(a);     <span class="hljs-comment">// prints 'global'  </span>
    <span class="hljs-built_in">console</span>.log(b);     <span class="hljs-comment">// prints 'outer'  </span>
    inner();  
  }  
outer();  
<span class="hljs-built_in">console</span>.log(a);         <span class="hljs-comment">// prints 'global'</span>
</code></pre>
<p>Here the <code>inner</code> function can access the variables defined in its own scope, the <code>outer</code> function’s scope, and the global scope. And the <code>outer</code> function can access the variable defined in its own scope and the global scope.</p>
<p>So a scope chain of the above code would be like this:</p>
<pre><code class="lang-text">Global {  
  outer {  
    inner  
  }  
}
</code></pre>
<p>Notice that <code>inner</code> function is surrounded by the lexical scope of <code>outer</code> function which is, in turn, surrounded by the global scope. That’s why the <code>inner</code> function can access the variables defined in <code>outer</code> function and the global scope.</p>
<h3 id="heading-practical-examples-of-closure">Practical Examples of Closure</h3>
<p>Let’s look at some practical examples of closures before diving into how closures work.</p>
<h4 id="heading-example-1">Example 1</h4>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">person</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> name = <span class="hljs-string">'Peter'</span>;  

  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayName</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-built_in">console</span>.log(name);  
  };  
}

<span class="hljs-keyword">let</span> peter = person();  
peter(); <span class="hljs-comment">// prints 'Peter'</span>
</code></pre>
<p>In this code, we are calling <code>person</code> function which returns inner function <code>displayName</code> and stores that inner function in <code>peter</code> variable. When we call <code>peter</code> function (which is actually referencing the <code>displayName</code> function), the name ‘Peter’ is printed to the console.</p>
<p>But we don’t have any variable named <code>name</code> in <code>displayName</code> function, so this function can somehow access the variable of its outer function <code>person</code> even after that function has returned. So the <code>displayName</code> function is actually a closure.</p>
<h4 id="heading-example-2">Example 2</h4>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCounter</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> counter = <span class="hljs-number">0</span>;  
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-keyword">return</span> counter++;  
  }  
}

<span class="hljs-keyword">let</span> count = getCounter();

<span class="hljs-built_in">console</span>.log(count());  <span class="hljs-comment">// 0  </span>
<span class="hljs-built_in">console</span>.log(count());  <span class="hljs-comment">// 1  </span>
<span class="hljs-built_in">console</span>.log(count());  <span class="hljs-comment">// 2</span>
</code></pre>
<p>Again we are storing the anonymous inner function returned by <code>getCounter</code> function into the <code>count</code> variable. As <code>count</code> function is now a closure, it can access the <code>counter</code> variable of <code>getCounter</code> function even after <code>getCounter()</code> has returned.</p>
<p>But notice that the value of the <code>counter</code> is not resetting to <code>0</code> on each <code>count</code> function call as it usually should.</p>
<p>That’s because, at each call of <code>count()</code>, a new scope for the function is created, but there is only single scope created for <code>getCounter</code> function, because the <code>counter</code> variable is defined in the scope of <code>getCounter()</code>, it would get incremented on each <code>count</code> function call instead of resetting to <code>0</code>.</p>
<h3 id="heading-how-do-closures-work">How do Closures Work?</h3>
<p>Up until now, we have discussed what closures are and their practical examples. Now let’s understand how closures really work in JavaScript.</p>
<p>To really understand how closures work in JavaScript, we have to understand the two most important concepts in JavaScript, that is, 1) Execution Context and 2) Lexical Environment.</p>
<h4 id="heading-execution-context">Execution Context</h4>
<p>An execution context is an abstract environment where the JavaScript code is evaluated and executed. When the global code is executed, it’s executed inside the global execution context, and the function code is executed inside the function execution context.</p>
<p>There can only be one currently running execution context (Because JavaScript is single threaded language), which is managed by a stack data structure known as Execution Stack or Call Stack.</p>
<p>An execution stack is a stack with LIFO (Last in, first out) structure in which items can only be added or removed from the top of the stack only.</p>
<p>The currently running execution context will be always on the top of the stack, and when the function which is currently running completes, its execution context is popped off from the stack and the control reaches to the execution context below it in the stack.</p>
<p>Let’s look at a code snippet to better understand execution context and stack:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198586956/rXNzD9ISFQ.png" alt /></p>
<p>When this code is executed, the JavaScript engine creates a global execution context to execute the global code, and when it encounters the call to <code>first()</code> function, it creates a new execution context for that function and pushes it to the top of the execution stack.</p>
<p>So the execution stack for the above code looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198588151/KXOygjIJ9J.png" alt /></p>
<p>When the <code>first()</code> function completes, its execution stack is removed from the stack, and the control reaches to execution context below it, that is, global execution context. So the remaining code in global scope will be executed.</p>
<h4 id="heading-lexical-environment">Lexical Environment</h4>
<p>Every time the JavaScript engine creates an execution context to execute the function or global code, it also creates a new lexical environment to store the variable defined in that function during the execution of that function.</p>
<p>A <em>lexical environment</em> is a data structure that holds <strong>identifier-variable mapping</strong>. (here <strong>identifier</strong> refers to the name of variables/functions, and the <strong>variable</strong> is the reference to actual object [including function type object] or primitive value).</p>
<p>A Lexical Environment has two components: (1) the <strong>environment record</strong> and (2) a <strong>reference to the outer environment</strong>.</p>
<ol>
<li>The <strong>environment record</strong> is the actual place where the variable and function declarations are stored.</li>
<li>The <strong>reference to the outer environment</strong> means it has access to its outer (parent) lexical environment. This component is the most important in order to understand how closures work.</li>
</ol>
<p>A lexical environment conceptually looks like this:</p>
<pre><code class="lang-text">lexicalEnvironment = {  
  environmentRecord: {  
    &lt;identifier&gt; : &lt;value&gt;,  
    &lt;identifier&gt; : &lt;value&gt;  
  }  
  outer: &lt; Reference to the parent lexical environment&gt;  
}
</code></pre>
<p>So let’s again take a look at above code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> a = <span class="hljs-string">'Hello World!'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">first</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> b = <span class="hljs-number">25</span>;    
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Inside first function'</span>);  
}  
first();  
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Inside global execution context'</span>);
</code></pre>
<p>When the JavaScript engine creates a global execution context to execute global code, it also creates a new lexical environment to store the variables and functions defined in the global scope. So the lexical environment for the global scope will look like this:</p>
<pre><code class="lang-javascript">globalLexicalEnvironment = {  
  <span class="hljs-attr">environmentRecord</span>: {  
      <span class="hljs-attr">a</span>     : <span class="hljs-string">'Hello World!'</span>,  
      <span class="hljs-attr">first</span> : &lt; reference to <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">object</span> &gt;  
  }  
  <span class="hljs-title">outer</span>: <span class="hljs-title">null</span>  
}</span>
</code></pre>
<p>Here the outer lexical environment is set to <code>null</code> because there is no outer lexical environment for the global scope.</p>
<p>When the engine creates execution context for <code>first()</code> function, it also creates a lexical environment to store variables defined in that function during execution of the function. So the lexical environment of the function will look like this:</p>
<pre><code class="lang-text">functionLexicalEnvironment = {  
  environmentRecord: {  
      b    : 25,  
  }  
  outer: &lt;globalLexicalEnvironment&gt;  
}
</code></pre>
<p>The outer lexical environment of the function is set to the global lexical environment because the function is surrounded by the global scope in the source code.</p>
<p><strong>Note —</strong> When a function completes, its execution context is removed from the stack, but its lexical environment may or may not be removed from the memory depending on if that lexical environment is referenced by any other lexical environments in their outer lexical environment property.</p>
<h3 id="heading-detailed-closures-examples">Detailed Closures Examples</h3>
<p>Now that we understand the execution context and lexical environment, let’s get back to the closures.</p>
<h4 id="heading-example-1">Example 1</h4>
<p>Take a look at this code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">person</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> name = <span class="hljs-string">'Peter'</span>;  

  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">displayName</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-built_in">console</span>.log(name);  
  };  
}

<span class="hljs-keyword">let</span> peter = person();  
peter(); <span class="hljs-comment">// prints 'Peter'</span>
</code></pre>
<p>When the <code>person</code> function is executed, the JavaScript engine creates a new execution context and lexical environment for the function. After this function finishes, it returns <code>displayName</code> function and assigns it to <code>peter</code> variable.</p>
<p>So its lexical environment will look like this:</p>
<pre><code class="lang-text">personLexicalEnvironment = {  
  environmentRecord: {  
    name : 'Peter',  
    displayName: &lt; displayName function reference&gt;  
  }  
  outer: &lt;globalLexicalEnvironment&gt;  
}
</code></pre>
<p>When the <code>person</code> function finishes, its execution context is removed from the stack. But its lexical environment is still in the memory because its lexical environment is referenced by the lexical environment of its inner <code>displayName</code> function. So its variables are still available in the memory.</p>
<p>Please note that when the <code>personLexicalEnvironment</code> is created, the JavaScript engine attaches the <code>personLexicalEnvironment</code> to all of the function definitions inside that lexical environment. So that later on if any of the inner functions are called, the JavaScript engine can set the outer lexical environment to the lexical environment attached to that function definition.</p>
<p>When the <code>peter</code> function is executed (which is actually a reference to the <code>displayName</code> function), the JavaScript engine creates a new execution context and lexical environment for that function.</p>
<p>So its lexical environment looks like this:</p>
<pre><code class="lang-text">displayNameLexicalEnvironment = {  
  environmentRecord: {  

  }  
  outer: &lt;personLexicalEnvironment&gt;  
}
</code></pre>
<p>As there’s no variable in <code>displayName</code> function, its environment record will be empty. During the execution of this function, the JavaScript engine will try to find the variable <code>name</code> in the function’s lexical environment.</p>
<p>As there are no variables in the lexical environment of <code>displayName</code> function, it will look into the outer lexical environment, that is, the lexical environment of the <code>person</code> function which still there in the memory. The JavaScript engine finds the variable and <code>name</code> is printed to the console.</p>
<h4 id="heading-example-2">Example 2</h4>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getCounter</span>(<span class="hljs-params"></span>) </span>{  
  <span class="hljs-keyword">let</span> counter = <span class="hljs-number">0</span>;  
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{  
    <span class="hljs-keyword">return</span> counter++;  
  }  
}

<span class="hljs-keyword">let</span> count = getCounter();

<span class="hljs-built_in">console</span>.log(count());  <span class="hljs-comment">// 0  </span>
<span class="hljs-built_in">console</span>.log(count());  <span class="hljs-comment">// 1  </span>
<span class="hljs-built_in">console</span>.log(count());  <span class="hljs-comment">// 2</span>
</code></pre>
<p>Again the lexical environment for the <code>getCounter</code> function will look like this:</p>
<pre><code class="lang-text">getCounterLexicalEnvironment = {  
  environmentRecord: {  
    counter: 0,  
    &lt;anonymous function&gt; : &lt; reference to function&gt;  
  }  
  outer: &lt;globalLexicalEnvironment&gt;  
}
</code></pre>
<p>This function returns an anonymous function and assigns it to <code>count</code> variable.</p>
<p>When the <code>count</code> function is executed, its lexical environment will look like this:</p>
<pre><code class="lang-text">countLexicalEnvironment = {  
  environmentRecord: {  

  }  
  outer: &lt;getCountLexicalEnvironment&gt;  
}
</code></pre>
<p>When the <code>count</code> function is called, the JavaScript engine will look into the lexical environment of this function for the <code>counter</code> variable. Again as its environment record is empty, the engine will look into the outer lexical environment of the function.</p>
<p>The engine finds the variable, prints it to the console and will increment the counter variable in the <code>getCounter</code> function lexical environment.</p>
<p>So the lexical environment for the <code>getCounter</code> function after first call <code>count</code> function will look like this:</p>
<pre><code class="lang-text">getCounterLexicalEnvironment = {  
  environmentRecord: {  
    counter: 1,  
    &lt;anonymous function&gt; : &lt; reference to function&gt;  
  }  
  outer: &lt;globalLexicalEnvironment&gt;  
}
</code></pre>
<p>On each call to the <code>count</code> function, the JavaScript engine creates a new lexical environment for the <code>count</code> function, increments the <code>counter</code> variable and updates the lexical environment of <code>getCounter</code> function to reflect changes.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>So we have learned what closures are and how they really work. Closures are fundamental concepts of JavaScript that every JavaScript developer should understand. Having a good knowledge of these concepts will help you to become a much more effective and better JavaScript developer.</p>
<p>That’s it and if you found this article helpful, please click the like 🙂 button, you can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora">Hashnode</a>, <a target="_blank" href="https://medium.com/@sukhjinder">Medium</a> and <a target="_blank" href="https://twitter.com/_sukh_arora">Twitter</a>, and if you have any doubt, feel free to comment! I’d be happy to help :)</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Asynchronous JavaScript]]></title><description><![CDATA[This article was originally published at: https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff
JavaScript is a single-threaded programming language which means only one thing can happen at a time. That is, the Java...]]></description><link>https://whatisweb.dev/understanding-asynchronous-javascript-the-event-loop-74cd408419ff</link><guid isPermaLink="true">https://whatisweb.dev/understanding-asynchronous-javascript-the-event-loop-74cd408419ff</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[webdev]]></category><category><![CDATA[asynchronous JavaScript]]></category><category><![CDATA[asynchronous]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Sun, 09 Oct 2022 13:50:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1665319404962/MeG-sluuk.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at: https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff</em></strong></p>
<p>JavaScript is a single-threaded programming language which means only one thing can happen at a time. That is, the JavaScript engine can only process one statement at a time in a single thread.</p>
<p>While the single-threaded languages simplify writing code because you don’t have to worry about concurrency issues, this also means you can’t perform long operations such as network access without blocking the main thread.</p>
<p>Imagine requesting some data from an API. Depending upon the situation the server might take some time to process the request while blocking the main thread making the web page unresponsive.</p>
<p>That’s where asynchronous JavaScript comes into play. Using asynchronous JavaScript (such as callbacks, promises, and async/await), you can perform long network requests without blocking the main thread.</p>
<p>While it’s not necessary that you learn all these concepts to be an awesome JavaScript developer, it’s helpful to know :)</p>
<p>So without further ado, Let’s get started :)</p>
<h3 id="heading-how-does-synchronous-javascript-work">How Does Synchronous JavaScript Work?</h3>
<p>Before we dive into asynchronous JavaScript, let’s first understand how the synchronous JavaScript code executes inside the JavaScript engine. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> second = <span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello there!'</span>);  
}

<span class="hljs-keyword">const</span> first = <span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hi there!'</span>);  
  second();  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'The End'</span>);  
}

first();
</code></pre>
<p>To understand how the above code executes inside the JavaScript engine, we have to understand the concept of the execution context and the call stack (also known as execution stack).</p>
<h4 id="heading-execution-context">Execution Context</h4>
<p>An Execution Context is an abstract concept of an environment where the JavaScript code is evaluated and executed. Whenever any code is run in JavaScript, it’s run inside an execution context.</p>
<p>The function code executes inside the function execution context, and the global code executes inside the global execution context. Each function has its own execution context.</p>
<h4 id="heading-call-stack">Call Stack</h4>
<p>The call stack as its name implies is a stack with a LIFO (Last in, First out) structure, which is used to store all the execution context created during the code execution.</p>
<p>JavaScript has a single call stack because it’s a single-threaded programming language. The call stack has a LIFO structure which means that the items can be added or removed from the top of the stack only.</p>
<p>Let’s get back to the above code snippet and try to understand how the code executes inside the JavaScript engine.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> second = <span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello there!'</span>);  
}

<span class="hljs-keyword">const</span> first = <span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hi there!'</span>);  
  second();  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'The End'</span>);  
}

first();
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198531899/rVkKoZDTZ.png" alt="Call Stack" />
<em>Call Stack for the above code</em></p>
<h4 id="heading-so-whats-happening-here">So What’s Happening Here?</h4>
<p>When this code is executed, a global execution context is created (represented by <code>main()</code>) and pushed to the top of the call stack. When a call to <code>first()</code> is encountered, it’s pushed to the top of the stack.</p>
<p>Next, <code>console.log('Hi there!')</code> is pushed to the top of the stack, when it finishes, it’s popped off from the stack. After it, we call <code>second()</code>, so the <code>second()</code> function is pushed to the top of the stack.</p>
<p><code>console.log('Hello there!')</code> is pushed to the top of the stack and popped off the stack when it finishes. The <code>second()</code> function finishes, so it’s popped off the stack.</p>
<p><code>console.log(‘The End’)</code> is pushed to the top of the stack and removed when it finishes. After it, the <code>first()</code> function completes, so it’s removed from the stack.</p>
<p>The program completes its execution at this point, so the global execution context(<code>main()</code>) is popped off from the stack.</p>
<h3 id="heading-how-does-asynchronous-javascript-work">How Does Asynchronous JavaScript Work?</h3>
<p>Now that we have a basic idea about the call stack, and how synchronous JavaScript works, let’s get back to asynchronous JavaScript.</p>
<h4 id="heading-what-is-blocking">What is Blocking?</h4>
<p>Let’s suppose we are doing image processing or a network request in a synchronous way. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> processImage = <span class="hljs-function">(<span class="hljs-params">image</span>) =&gt;</span> {  
  <span class="hljs-comment">/**  
  * doing some operations on image  
  **/</span>  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Image processed'</span>);  
}

<span class="hljs-keyword">const</span> networkRequest = <span class="hljs-function">(<span class="hljs-params">url</span>) =&gt;</span> {  
  <span class="hljs-comment">/**  
  * requesting network resource  
  **/</span>  
  <span class="hljs-keyword">return</span> someData;  
}

<span class="hljs-keyword">const</span> greeting = <span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello World'</span>);  
}

processImage(logo.jpg);  
networkRequest(<span class="hljs-string">'www.somerandomurl.com'</span>);  
greeting();
</code></pre>
<p>Doing image processing and network request takes time. So when <code>processImage()</code> function is called, it’s going to take some time depending on the size of the image.</p>
<p>When the <code>processImage()</code> function completes, it’s removed from the stack. After that, the <code>networkRequest()</code> function is called and pushed to the stack. Again it’s also going to take some time to finish execution.</p>
<p>At last when the <code>networkRequest()</code> function completes, <code>greeting()</code> function is called and since it contains only a <code>console.log</code> statement and <code>console.log</code> statements are generally fast, so the <code>greeting()</code> function is immediately executed and returned.</p>
<p>So you see, we have to wait until the function (such as <code>processImage()</code> or <code>networkRequest()</code>) has finished. This means these functions are blocking the call stack or main thread. So we can’t perform any other operation while the above code is executing which is not ideal.</p>
<h4 id="heading-so-whats-the-solution">So what’s the solution?</h4>
<p>The simplest solution is asynchronous callbacks. We use asynchronous callbacks to make our code non-blocking. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> networkRequest = <span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {  
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Async Code'</span>);  
  }, <span class="hljs-number">2000</span>);  
};

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello World'</span>);

networkRequest();
</code></pre>
<p>Here I have used <code>setTimeout</code> method to simulate the network request. Please keep in mind that the <code>setTimeout</code> is not a part of the JavaScript engine, it’s a part of something known as web APIs (in browsers) and C/C++ APIs (in node.js).</p>
<p>To understand how this code is executed we have to understand a few more concepts such event loop and the callback queue (also known as the task queue or the message queue).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198533327/GzSvrnQr4.png" alt="JavaScript Runtime Environment" />
<em>An Overview of JavaScript Runtime Environment</em></p>
<p>The <strong>event loop</strong>, the <strong>web APIs</strong>, and the <strong>message queue</strong>/<strong>task queue</strong> are not part of the JavaScript engine, it’s a part of the browser’s JavaScript runtime environment or Nodejs JavaScript runtime environment (in the case of Nodejs). In Nodejs, the web APIs are replaced by the C/C++ APIs.</p>
<p>Now let’s get back to the above code and see how it’s executed in an asynchronous way.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> networkRequest = <span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {  
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Async Code'</span>);  
  }, <span class="hljs-number">2000</span>);  
};

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello World'</span>);

networkRequest();

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'The End'</span>);
</code></pre>
<p><img src="https://miro.medium.com/max/720/1*sOz5cj-_Jjv23njWg_-uGA.gif" alt="Event Loop" />
<em>Event Loop</em></p>
<p>When the above code loads in the browser, the <code>console.log(‘Hello World’)</code> is pushed to the stack and popped off the stack after it’s finished. Next, a call to <code>networkRequest()</code> is encountered, so it’s pushed to the top of the stack.</p>
<p>Next <code>setTimeout()</code> function is called, so it’s pushed to the top of the stack. The <code>setTimeout()</code> has two arguments: 1) callback and 2) time in milliseconds (ms).</p>
<p>The <code>setTimeout()</code> method starts a timer of <code>2s</code> in the web APIs environment. At this point, the <code>setTimeout()</code> has finished and it’s popped off from the stack. After it, <code>console.log('The End')</code> is pushed to the stack, executed, and removed from the stack after its completion.</p>
<p>Meanwhile, the timer has expired, and now the callback is pushed to the <strong>message queue</strong>. But the callback is not immediately executed, and that’s where the event loop kicks in.</p>
<h4 id="heading-the-event-loop">The Event Loop</h4>
<p>The job of the Event loop is to look into the call stack and determine if the call stack is empty or not. If the call stack is empty, it looks into the message queue to see if there’s any pending callback waiting to be executed.</p>
<p>In this case, the message queue contains one callback, and the call stack is empty at this point. So the Event loop pushes the callback to the top of the stack.</p>
<p>After that the <code>console.log(‘Async Code’)</code> is pushed to the top of the stack, executed and popped off from the stack. At this point, the callback has finished so it’s removed from the stack and the program finally finishes.</p>
<h4 id="heading-dom-events">DOM Events</h4>
<p>The <strong>Message queue</strong> also contains the callbacks from the DOM events such as click events and keyboard events. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.btn'</span>).addEventListener(<span class="hljs-string">'click'</span>,<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Button Clicked'</span>);  
});
</code></pre>
<p>In the case of DOM events, the event listener sits in the web APIs environment waiting for a certain event (click event in this case) to happen, and when that event happens, then the callback function is placed in the message queue waiting to be executed.</p>
<p>Again the event loop checks if the call stack is empty and pushes the event callback to the stack if it’s empty and the callback is executed.</p>
<p>We have learned how the asynchronous callbacks and DOM events are executed which uses the message queue to store all the callbacks waiting to be executed.</p>
<h4 id="heading-es6-job-queue-micro-task-queue">ES6 Job Queue/ Micro-Task queue</h4>
<p>ES6 introduced the concept of job queue/micro-task queue which is used by Promises in JavaScript. The difference between the message queue and the job queue is that the job queue has a higher priority than the message queue, which means that promise jobs inside the job queue/ micro-task queue will be executed before the callbacks inside the message queue.</p>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Script start'</span>);

<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'setTimeout'</span>);  
}, <span class="hljs-number">0</span>);

<span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {  
    resolve(<span class="hljs-string">'Promise resolved'</span>);  
  }).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(res))  
    .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(err));

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Script End'</span>);
</code></pre>
<p>Output:</p>
<pre><code class="lang-text">Script start  
Script End  
Promise resolved  
setTimeout
</code></pre>
<p>We can see that the promise is executed before the <code>setTimeout</code> because the promise response is stored inside the micro-task queue which has a higher priority than the message queue.</p>
<p>Let’s take another example, this time with two promises and two setTimeout. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Script start'</span>);

<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'setTimeout 1'</span>);  
}, <span class="hljs-number">0</span>);

<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'setTimeout 2'</span>);  
}, <span class="hljs-number">0</span>);

<span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {  
    resolve(<span class="hljs-string">'Promise 1 resolved'</span>);  
  }).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(res))  
    .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(err));

<span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {  
    resolve(<span class="hljs-string">'Promise 2 resolved'</span>);  
  }).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(res))  
    .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(err));

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Script End'</span>);
</code></pre>
<p>This prints:</p>
<pre><code class="lang-text">Script start  
Script End  
Promise 1 resolved  
Promise 2 resolved  
setTimeout 1  
setTimeout 2
</code></pre>
<p>We can see that the two promises are executed before the callbacks in the <code>setTimeout</code> because the event loop prioritizes the tasks in the micro-task queue over the tasks in the message queue/task queue.</p>
<p>While the event loop is executing the tasks in the micro-task queue and in that time if another promise is resolved, it will be added to the end of the same micro-task queue, and it will be executed before the callbacks inside the message queue no matter for how much time the callback is waiting to be executed.</p>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Script start'</span>);

<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {  
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'setTimeout'</span>);  
}, <span class="hljs-number">0</span>);

<span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {  
    resolve(<span class="hljs-string">'Promise 1 resolved'</span>);  
  }).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(res));

<span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {  
  resolve(<span class="hljs-string">'Promise 2 resolved'</span>);  
  }).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {  
       <span class="hljs-built_in">console</span>.log(res);  
       <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {  
         resolve(<span class="hljs-string">'Promise 3 resolved'</span>);  
       })  
     }).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(res));

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Script End'</span>);
</code></pre>
<p>This prints:</p>
<pre><code class="lang-text">Script start  
Script End  
Promise 1 resolved  
Promise 2 resolved  
Promise 3 resolved  
setTimeout
</code></pre>
<p>So all the tasks in the micro-task queue will be executed before the tasks in the message queue. That is, the event loop will first empty the micro-task queue before executing any callback in the message queue.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>So we have learned how asynchronous JavaScript works and other concepts such as call stack, event loop, message queue/task queue, and job queue/micro-task queue which together make the JavaScript runtime environment. While it’s not necessary that you learn all these concepts to be an awesome JavaScript developer, it’s helpful to know these concepts :)</p>
<p>That’s it and if you found this article helpful, please click the clap 👏button, you can also follow me on <a target="_blank" href="https://hashnode.com/@SukhjinderArora">Hashnode</a> and <a target="_blank" href="https://twitter.com/_sukh_arora">Twitter</a>, and if you have any doubt, feel free to comment! I’d be happy to help :)</p>
]]></content:encoded></item><item><title><![CDATA[A Practical Guide to Regular Expressions (RegEx) In JavaScript]]></title><description><![CDATA[When you first encounter Regular Expressions, they may seem like a random string of gibberish. While they might look awkward (with somewhat confusing syntax), they are also extremely useful.
The truth is properly understanding regular expressions wil...]]></description><link>https://whatisweb.dev/a-beginners-guide-to-regular-expressions-regex-in-javascript</link><guid isPermaLink="true">https://whatisweb.dev/a-beginners-guide-to-regular-expressions-regex-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Regex]]></category><category><![CDATA[Regular Expressions]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Sat, 08 Oct 2022 09:18:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/_oKSYD2cSIk/upload/v1665217110814/VRc_ncBai.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you first encounter Regular Expressions, they may seem like a random string of gibberish. While they might look awkward (with somewhat confusing syntax), they are also extremely useful.</p>
<p>The truth is properly understanding regular expressions will make you a much more effective programmer. To fully understand the regex world, you first need to learn the basics concepts, on which you can later build.</p>
<p>So, without further ado, let's get started :)</p>
<h3 id="heading-what-are-regular-expressions">What are Regular Expressions?</h3>
<p>Regular expressions are a way to describe patterns in a string data. They form a small language of its own, which is a part of many programming languages like JavaScript, Perl, Python, PHP, and Java.</p>
<p>Regular expressions allow you to check a string of characters like an e-mail address or password for patterns, to see so if they match the pattern defined by that regular expression and produce actionable information.</p>
<h3 id="heading-creating-a-regular-expression">Creating a Regular Expression</h3>
<p>There are two ways to create a regular expression in JavaScript. It can be either created with the RegExp constructor or by using forward slashes ( / ) to enclose the pattern.</p>
<h4 id="heading-regular-expression-constructor">Regular Expression Constructor:</h4>
<p>Syntax: <code>new RegExp(pattern[, flags])</code></p>
<p>Example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regexConst = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'abc'</span>);
</code></pre>
<h4 id="heading-regular-expression-literal">Regular Expression Literal:</h4>
<p><strong>Syntax:</strong> <code>/pattern/flags</code></p>
<p>Example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regexLiteral = <span class="hljs-regexp">/abc/</span>;
</code></pre>
<ul>
<li>Here the flags are optional, I will explain these later in this article.</li>
</ul>
<p>There might also be cases where you want to create regular expressions dynamically, in which case regex literal won’t work, so you have to use a regular expression constructor.</p>
<p>No matter which method you choose, the result is going to be a regex object. Both regex objects will have the same methods and properties attached to them.</p>
<p><strong>Since forward slashes are used to enclose patterns in the above example, you have to escape the forward slash</strong> <code>**( / )**</code> <strong>with a backslash</strong> <code>**( \ )**</code> <strong>if you want to use it as a part of the regex.</strong></p>
<h3 id="heading-regular-expressions-methods">Regular Expressions Methods</h3>
<p>There are mainly two methods for testing regular expressions.</p>
<h4 id="heading-regexpprototypetest">RegExp.prototype.test()</h4>
<p>This method is used to test whether a match has been found or not. It accepts a string which we have to test against a regular expression and returns <code>true</code> or <code>false</code> depending upon if the match is found or not.</p>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/hello/</span>;

<span class="hljs-keyword">var</span> str = <span class="hljs-string">'hello world'</span>;

<span class="hljs-keyword">var</span> result = regex.test(str);

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

<span class="hljs-comment">// returns true</span>
</code></pre>
<h4 id="heading-regexpprototypeexec">RegExp.prototype.exec()</h4>
<p>This method returns an array containing all the matched groups. It accepts a string that we have to test against a regular expression.</p>
<p>For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/hello/</span>;

<span class="hljs-keyword">var</span> str = <span class="hljs-string">'hello world'</span>;

<span class="hljs-keyword">var</span> result = regex.exec(str);

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

<span class="hljs-comment">// returns \[ 'hello', index: 0, input: 'hello world', groups: undefined \]</span>

<span class="hljs-comment">// 'hello' -&gt; is the matched pattern.  </span>
<span class="hljs-comment">// index: -&gt; Is where the regular expression starts.  </span>
<span class="hljs-comment">// input: -&gt; Is the actual string passed.</span>
</code></pre>
<p>We are going to use the <code>test()</code> method in this article.</p>
<h3 id="heading-simple-regex-patterns">Simple Regex Patterns</h3>
<p>It is the most basic pattern, which simply matches the literal text with the test string. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/hello/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'hello world'</span>));

<span class="hljs-comment">// true</span>
</code></pre>
<h3 id="heading-special-characters">Special Characters</h3>
<p>Up until now, we’ve created simple regular expression patterns. Now, let’s tap into the full power of regular expressions when handling more complex cases.</p>
<p>For example, instead of matching a specific email address let’s say we’d like to match many email addresses. That’s where special characters come into play. There are special symbols and characters that you have to memorize to fully understand the regular expressions.</p>
<h4 id="heading-flags">Flags:</h4>
<p>Regular expressions have five optional flags or modifiers. Let’s discuss the two most important flags:</p>
<ul>
<li><p><strong>g</strong> — Global search, don’t return after the first match</p>
</li>
<li><p><strong>i</strong> — Case-insensitive search</p>
</li>
</ul>
<p>You can also combine the flags in a single regular expression. Note that their order doesn’t have any effect on the result.</p>
<p>Let’s look at some code examples:</p>
<p><strong>Regular Expression Literal —</strong> <em>Syntax</em> <code>/pattern/flags</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regexGlobal = <span class="hljs-regexp">/abc/g</span>;

<span class="hljs-built_in">console</span>.log(regexGlobal.test(<span class="hljs-string">'abc abc'</span>));

<span class="hljs-comment">// it will match all the occurrences of 'abc', so it won't return   </span>
<span class="hljs-comment">// after the first match.</span>

<span class="hljs-keyword">var</span> regexInsensitive = <span class="hljs-regexp">/abc/i</span>;

<span class="hljs-built_in">console</span>.log(regexInsensitive.test(<span class="hljs-string">'Abc'</span>));

<span class="hljs-comment">// returns true because the case of string characters doesn't matter   </span>
<span class="hljs-comment">// in case-insensitive search.</span>
</code></pre>
<p><strong>Regular Expression Constructor —</strong> <em>Syntax</em> <code>new RegExp('pattern', 'flags')</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regexGlobal = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'abc'</span>,<span class="hljs-string">'g'</span>)

<span class="hljs-built_in">console</span>.log(regexGlobal.test(<span class="hljs-string">'abc abc'</span>));

<span class="hljs-comment">// it will match all the occurrences of 'abc', so it won't return // after the first match.</span>

<span class="hljs-keyword">var</span> regexInsensitive = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'abc'</span>,<span class="hljs-string">'i'</span>)

<span class="hljs-built_in">console</span>.log(regexInsensitive.test(<span class="hljs-string">'Abc'</span>));

<span class="hljs-comment">// returns true, because the case of string characters doesn't matter in a case-insensitive search.</span>
</code></pre>
<h4 id="heading-character-groups">Character groups:</h4>
<p><strong>Character set [xyz] —</strong> A character set is a way to match different characters in a single position, it matches any single character in the string from characters present inside the brackets. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/\[bt\]ear/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'tear'</span>));  
<span class="hljs-comment">// returns true  </span>
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'bear'</span>));  
<span class="hljs-comment">// return true  </span>
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'fear'</span>));  
<span class="hljs-comment">// return false</span>
</code></pre>
<p><strong>Note —</strong> All the special characters except for caret <code>(^)</code> (Which has an entirely different meaning inside the character set) lose their special meaning inside the character set.</p>
<p><strong>Negated character set [^xyz] —</strong> It matches anything that is not enclosed in the brackets. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/\[^bt\]ear/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'tear'</span>));  
<span class="hljs-comment">// returns false  </span>
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'bear'</span>));  
<span class="hljs-comment">// return false  </span>
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'fear'</span>));  
<span class="hljs-comment">// return true</span>
</code></pre>
<p><strong>Ranges [a-z] —</strong> Suppose we want to match all of the letters of an alphabet in a single position, we could write all the letters inside the brackets, but there is an easier way and that is <strong>ranges</strong>. For example: <strong>[a-h]</strong> will match all the letters from a to h. Ranges can also be digits like <strong>[0-9]</strong> or capital letters like <strong>[A-Z]</strong>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/\[a-z\]ear/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'fear'</span>));  
<span class="hljs-comment">// returns true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'tear'</span>));  
<span class="hljs-comment">// returns true</span>
</code></pre>
<p><strong>Meta-characters —</strong> Meta-characters are characters with a special meaning. There are many meta characters but I am going to cover the most important ones here.</p>
<ul>
<li><p><strong>\d</strong> — Match any digit character ( same as <code>[0-9]</code> ).</p>
</li>
<li><p><strong>\w</strong> — Match any word character. A word character is any letter, digit, and underscore. (Same as <code>[a-zA-Z0–9_]</code> ) i.e alphanumeric character.</p>
</li>
<li><p><strong>\s</strong> — Match a whitespace character (spaces, tabs etc.).</p>
</li>
<li><p><strong>\t</strong> — Match a tab character only.</p>
</li>
<li><p><strong>\b</strong> — Find a match at the beginning or end of a word. Also known as the word boundary.</p>
</li>
<li><p><strong>.</strong> — (period) Matches any character except for the new line.</p>
</li>
<li><p><strong>\D</strong> — Match any non-digit character (same as <code>[^0–9]</code>).</p>
</li>
<li><p><strong>\W</strong> — Match any non-word character (Same as <code>[^a-zA-Z0–9_]</code> ).</p>
</li>
<li><p><strong>\S</strong> — Match a non-whitespace character.</p>
</li>
</ul>
<p><strong>Quantifiers: —</strong> Quantifiers are symbols that have a special meaning in a regular expression.</p>
<ul>
<li><strong>+</strong> — Matches the preceding expression 1 or more times.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/\\d+/</span>;  
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'8'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'88899'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'8888845'</span>));  
<span class="hljs-comment">// true</span>
</code></pre>
<ul>
<li><strong>*</strong> —Matches the preceding expression 0 or more times.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/go\*d/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'gd'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'god'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'good'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'goood'</span>));  
<span class="hljs-comment">// true</span>
</code></pre>
<ul>
<li><strong>?</strong> — Matches the preceding expression 0 or 1 time, that is preceding pattern is optional.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/goo?d/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'god'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'good'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'goood'</span>));  
<span class="hljs-comment">// false</span>
</code></pre>
<ul>
<li><strong>^</strong> — Matches the beginning of the string, the regular expression that follows it should be at the start of the test string. i.e. the caret (^) matches the start of the string.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/^g/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'good'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'bad'</span>));  
<span class="hljs-comment">// false</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'tag'</span>));  
<span class="hljs-comment">// false</span>
</code></pre>
<ul>
<li><strong>$</strong> — Matches the end of the string, that is the regular expression that precedes it should be at the end of the test string. The dollar ($) sign matches the end of the string.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/.com$/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'test@testmail.com'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'test@testmail'</span>));  
<span class="hljs-comment">// false</span>
</code></pre>
<ul>
<li><strong>{N}</strong> — Matches exactly N occurrences of the preceding regular expression.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/go{2}d/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'good'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'god'</span>));  
<span class="hljs-comment">// false</span>
</code></pre>
<ul>
<li><strong>{N,}</strong> — Matches at least N occurrences of the preceding regular expression.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/go{2,}d/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'good'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'goood'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'gooood'</span>));  
<span class="hljs-comment">// true</span>
</code></pre>
<ul>
<li><strong>{N,M}</strong> — Matches at least N occurrences and at most M occurrences of the preceding regular expression (where M &gt; N).</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/go{1,2}d/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'god'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'good'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'goood'</span>));  
<span class="hljs-comment">// false</span>
</code></pre>
<p><strong>Alternation X|Y</strong> — Matches either X or Y. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/(green|red) apple/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'green apple'</span>));  
<span class="hljs-comment">// true  </span>
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'red apple'</span>));  
<span class="hljs-comment">// true  </span>
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'blue apple'</span>));  
<span class="hljs-comment">// false</span>
</code></pre>
<p><strong>Note</strong> — If you want to use any special character as a part of the expression, say for example you want to match literal <code>+</code> or <code>.</code>, then you have to escape them with a backslash <code>( \ )</code>. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/a+b/</span>;  <span class="hljs-comment">// This won't work</span>

<span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/a\\+b/</span>; <span class="hljs-comment">// This will work</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'a+b'</span>)); <span class="hljs-comment">// true</span>
</code></pre>
<h4 id="heading-advanced">Advanced</h4>
<p><strong>(x)</strong> — Matches x and remembers the match. These are called capturing groups. This is also used to create subexpressions within a regular expression. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/(foo)bar\\1/</span>;  
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'foobarfoo'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'foobar'</span>));  
<span class="hljs-comment">// false</span>
</code></pre>
<p><code>\1</code> remembers and uses that match from the first subexpression within parentheses.</p>
<p><strong>(?:x)</strong> — Matches x and does not remember the match. These are called non-capturing groups. Here <code>\1</code> won’t work, it will match the literal <code>\1</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/(?:foo)bar\\1/</span>;  
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'foobarfoo'</span>));  
<span class="hljs-comment">// false</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'foobar'</span>));  
<span class="hljs-comment">// false</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'foobar\\1'</span>));  
<span class="hljs-comment">// true</span>
</code></pre>
<p><strong>x(?=y)</strong> — Matches x only if x is followed by y. Also called a positive look ahead. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/Red(?=Apple)/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'RedApple'</span>));  
<span class="hljs-comment">// true</span>
</code></pre>
<p>In the above example, a match will occur only if <code>Red</code> is followed by <code>Apple</code>.</p>
<h3 id="heading-practicing-regex">Practicing Regex:</h3>
<p>Let’s practice some of the concepts that we have learned above.</p>
<ul>
<li><strong>Match any 10-digit number :</strong></li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/^\\d{10}$/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'9995484545'</span>));  
<span class="hljs-comment">// true</span>
</code></pre>
<p>Let’s break that down and see what’s going on up there.</p>
<ol>
<li><p>If we want to enforce that the match must span the whole string, we can add the quantifiers <code>^</code> and <code>$</code>. The caret <code>^</code> matches the start of the input string, whereas the dollar sign <code>$</code> matches the end. So, it would not match if the string contained more than 10 digits.</p>
</li>
<li><p><code>\d</code> matches any digit character.</p>
</li>
<li><p><code>{10}</code> matches the previous expression, in this case, <code>\d</code> exactly 10 times. So, if the test string contains less than or more than 10 digits, the result will be false.</p>
</li>
</ol>
<ul>
<li><strong>Match a date with the following format</strong> <code>DD-MM-YYYY</code> or <code>DD-MM-YY</code></li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/^(\\d{1,2}-){2}\\d{2}(\\d{2})?$/</span>;  
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'01-01-1990'</span>));  
<span class="hljs-comment">// true  </span>
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'01-01-90'</span>));  
<span class="hljs-comment">// true  </span>
<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'01-01-190'</span>));  
<span class="hljs-comment">// false</span>
</code></pre>
<p>Let’s break that down and see what’s going on up there.</p>
<ol>
<li><p>Again, we have wrapped the entire regular expression inside <code>^</code> and <code>$</code>, so that the match spans the entire string.</p>
</li>
<li><p><code>(</code> start of the first subexpression.</p>
</li>
<li><p><code>\d{1,2}</code> matches at least 1 digit and at most 2 digits.</p>
</li>
<li><p><code>-</code> matches the literal hyphen character.</p>
</li>
<li><p><code>)</code> end of the first subexpression.</p>
</li>
<li><p><code>{2}</code> match the first subexpression exactly two times.</p>
</li>
<li><p><code>\d{2}</code> matches exactly two digits.</p>
</li>
<li><p><code>(\d{2})?</code> matches exactly two digits. But it’s optional, so either year contains 2 digits or 4 digits.</p>
</li>
</ol>
<ul>
<li><strong>Matching Anything But a Newline</strong></li>
</ul>
<p>The expression should match any string with a format like <code>abc.def.ghi.jkl</code> where each variable <code>a, b, c, d, e, f, g, h, i, j, k, l</code> can be any character except new line.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">var</span> regex = <span class="hljs-regexp">/^(.{3}\\.){3}.{3}$/</span>;

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'123.456.abc.def'</span>));  
<span class="hljs-comment">// true</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'1243.446.abc.def'</span>));  
<span class="hljs-comment">// false</span>

<span class="hljs-built_in">console</span>.log(regex.test(<span class="hljs-string">'abc.def.ghi.jkl'</span>));  
<span class="hljs-comment">// true</span>
</code></pre>
<p>Let’s break that down and see what’s going on up there.</p>
<ol>
<li><p>We have wrapped the entire regular expression inside <code>^</code> and <code>$</code> so that the match spans the entire string.</p>
</li>
<li><p><code>(</code> start of the first subexpression</p>
</li>
<li><p><code>.{3}</code> matches any character except the new line for exactly 3 times.</p>
</li>
<li><p><code>\.</code> matches the literal <code>.</code> period</p>
</li>
<li><p><code>)</code> end of the first subexpression</p>
</li>
<li><p><code>{3}</code> matches the first subexpression exactly 3 times.</p>
</li>
<li><p><code>.{3}</code> matches any character except the new line for exactly 3 times.</p>
</li>
</ol>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Regular expression can be fairly complex at times, but having a proper understanding of the above concepts will help you understand more complex regex patterns easily. You can learn more about regex <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">here</a> and practice it <a target="_blank" href="https://hackerrank.com/domains/regex">here</a>.</p>
<p>**That’s it and if you found this article helpful, please hit the 🙂 button and share the article, so that others can find it easily :) You can also follow me ** <a target="_blank" href="https://whatisweb.dev/"><strong>here</strong></a> <strong>and on</strong> <a target="_blank" href="https://twitter.com/_sukh_arora"><strong>Twitter</strong></a> <strong>:)</strong></p>
]]></content:encoded></item><item><title><![CDATA[How to Build a Responsive Navigation Bar using CSS Flexbox and JavaScript]]></title><description><![CDATA[This article was originally published at: https://itnext.io/how-to-build-a-responsive-navbar-using-flexbox-and-javascript-eb0af24f19bf
In this article, we will create a fully responsive navigation bar from scratch using only flexbox and a little bit ...]]></description><link>https://whatisweb.dev/how-to-build-a-responsive-navbar-using-flexbox-and-javascript</link><guid isPermaLink="true">https://whatisweb.dev/how-to-build-a-responsive-navbar-using-flexbox-and-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[CSS]]></category><category><![CDATA[flexbox]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Sukhjinder Arora]]></dc:creator><pubDate>Sat, 08 Oct 2022 03:56:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/ipARHaxETRk/upload/v1665199443616/V6J4IVySD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><em>This article was originally published at: https://itnext.io/how-to-build-a-responsive-navbar-using-flexbox-and-javascript-eb0af24f19bf</em></strong></p>
<p>In this article, we will create a fully responsive navigation bar from scratch using only flexbox and a little bit of JavaScript (for the toggle menu). So, I will assume you have basic knowledge of HTML, CSS, and JavaScript, that is, you should know the basic HTML tags and how to link the CSS and JavaScript files to HTML files.</p>
<p>I will be taking the mobile first approach for building the navigation bar. That is, we will first make the navigation bar for mobile devices and then for the desktop using media queries.</p>
<h3 id="heading-getting-started"><strong>Getting started</strong></h3>
<p>Here’s the basic HTML for the layout:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span>&gt;</span>logo<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"main-nav"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"js-menu"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>About Us<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>Contact Us<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
</code></pre>
<p>You can use any name for classes and Ids.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198555846/nsS-0r9EDU.jpeg" alt /></p>
<p>This is what we got after writing the above code, this isn’t much, but we will make it better by styling it using CSS.</p>
<p>Let's add some basic styling to make it look nice:</p>
<pre><code class="lang-css">* {  
    <span class="hljs-attribute">box-sizing</span>: border-box;  
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;  
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;  
}
<span class="hljs-selector-tag">body</span> {  
    <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Josefin Sans'</span>, sans-serif;  
}
<span class="hljs-selector-class">.navbar</span> {  
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;  
    <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">260deg</span>, #<span class="hljs-number">2376</span>ae <span class="hljs-number">0%</span>, #c16ecf   <span class="hljs-number">100%</span>);  
    <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.2</span>);  
    <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">10px</span>;  
}
<span class="hljs-selector-class">.main-nav</span> {  
    <span class="hljs-attribute">list-style-type</span>: none;  
}
<span class="hljs-selector-class">.nav-links</span>,  
<span class="hljs-selector-class">.logo</span> {  
    <span class="hljs-attribute">text-decoration</span>: none;  
    <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0.7</span>);  
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198556975/0SohgexFPt.png" alt /></p>
<p>This certainly looks much better, I have stripped off any default browser specific padding and margin of every element using the universal selector (*), and set the box-sizing to border-box to make it easy to resize elements.</p>
<p>I have used ‘Josefin Sans’ font for the navigation bar and a linear-gradient for the background. You can choose your own fonts, colors, and background.</p>
<p>Now add some padding and margin to make it look better.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.main-nav</span> <span class="hljs-selector-tag">li</span> {  
    <span class="hljs-attribute">text-align</span>: center;  
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">15px</span> auto;  
}
<span class="hljs-selector-class">.logo</span> {  
    <span class="hljs-attribute">display</span>: inline-block;  
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">22px</span>;  
    <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;  
    <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">20px</span>;  
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198558410/Q7XYGrd9h.png" alt /></p>
<h3 id="heading-the-toggle-button">The Toggle Button</h3>
<p>It’s starting to look good. Now let’s add a little toggle button at the top right corner. For this, I am going to use Font Awesome icons.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198559719/FB6cKVMZ7.png" alt /></p>
<p>This is what it looks like. Notice the little hamburger icon in the top left corner, this is looking weird. So let’s reposition and style it.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.navbar-toggle</span> {  
    <span class="hljs-attribute">position</span>: absolute;  
    <span class="hljs-attribute">top</span>: <span class="hljs-number">10px</span>;  
    <span class="hljs-attribute">right</span>: <span class="hljs-number">20px</span>;  
    <span class="hljs-attribute">cursor</span>: pointer;   
    <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>,<span class="hljs-number">255</span>,<span class="hljs-number">255</span>,<span class="hljs-number">0.8</span>);  
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24px</span>;  
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198560968/Ky3ziSxjRx.png" alt /></p>
<p>The navbar for mobile devices is almost complete now. Let’s add a little bit of JavaScript to enable the toggle menu.</p>
<p>I have hidden the menu so that it’s not visible by default.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.main-nav</span> {  
    <span class="hljs-attribute">list-style-type</span>: none;  
    <span class="hljs-attribute">display</span>: none;  
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198562148/0aNkxqZyh.png" alt /></p>
<p>Now let’s add some JavaScript code to make it visible when someone clicks on the hamburger icon.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> mainNav = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'js-menu'</span>);
<span class="hljs-keyword">let</span> navBarToggle = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'js-navbar-toggle'</span>);

navBarToggle.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{  
    mainNav.classList.toggle(<span class="hljs-string">'active'</span>);
});
</code></pre>
<p>This code toggles the active class on the menu list. So add the following code in the CSS file.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.active</span> {  
  <span class="hljs-attribute">display</span>: block;  
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198563533/ax9vq_Orl.gif" alt /></p>
<p>Nice and easy, with that our mobile part is over, now let’s move to the desktop part.</p>
<h3 id="heading-for-desktop">For Desktop:</h3>
<p>for desktop, all we have to do is to change the flex-direction property to row and give a .navbar class a display property of flex.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">768px</span>) {
    <span class="hljs-selector-class">.navbar</span> {  
        <span class="hljs-attribute">display</span>: flex;  
        <span class="hljs-attribute">justify-content</span>: space-between;  
        <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">0</span>;  
        <span class="hljs-attribute">height</span>: <span class="hljs-number">70px</span>;  
        <span class="hljs-attribute">align-items</span>: center;  
    }
    <span class="hljs-selector-class">.main-nav</span> {  
        <span class="hljs-attribute">display</span>: flex;  
        <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">30px</span>;  
        <span class="hljs-attribute">flex-direction</span>: row;  
        <span class="hljs-attribute">justify-content</span>: flex-end;  
    }
    <span class="hljs-selector-class">.main-nav</span> <span class="hljs-selector-tag">li</span> {  
        <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;  
    }
    <span class="hljs-selector-class">.nav-links</span> {  
        <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">40px</span>;  
    }
    <span class="hljs-selector-class">.logo</span> {  
        <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">0</span>;  
    }
   <span class="hljs-selector-class">.navbar-toggle</span> {  
       <span class="hljs-attribute">display</span>: none;  
    }
    <span class="hljs-selector-class">.logo</span>*<span class="hljs-selector-pseudo">:hover</span>*,  
    <span class="hljs-selector-class">.nav-links</span>*<span class="hljs-selector-pseudo">:hover</span>* {  
        <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">1</span>);  
    }
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1665198565235/k6XUGZTah.png" alt /></p>
<h3 id="heading-final-code">Final Code:</h3>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-toggle"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"js-navbar-toggle"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fas fa-bars"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span>&gt;</span>logo<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"main-nav"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"js-menu"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>Products<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>About Us<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>Contact Us<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-links"</span>&gt;</span>Blog<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
</code></pre>
<pre><code class="lang-css">* {
   <span class="hljs-attribute">box-sizing</span>: border-box;
   <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
   <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
}

<span class="hljs-selector-tag">body</span> {
   <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Josefin Sans'</span>, sans-serif;
}

<span class="hljs-selector-class">.navbar</span> {
   <span class="hljs-attribute">font-size</span>: <span class="hljs-number">18px</span>;
   <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">260deg</span>, #<span class="hljs-number">2376</span>ae <span class="hljs-number">0%</span>, #c16ecf <span class="hljs-number">100%</span>);
   <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.2</span>);
   <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.main-nav</span> {
   <span class="hljs-attribute">list-style-type</span>: none;
   <span class="hljs-attribute">display</span>: none;
}

<span class="hljs-selector-class">.nav-links</span>,
<span class="hljs-selector-class">.logo</span> {
   <span class="hljs-attribute">text-decoration</span>: none;
   <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0.7</span>);
}

<span class="hljs-selector-class">.main-nav</span> <span class="hljs-selector-tag">li</span> {
   <span class="hljs-attribute">text-align</span>: center;
   <span class="hljs-attribute">margin</span>: <span class="hljs-number">15px</span> auto;
}

<span class="hljs-selector-class">.logo</span> {
   <span class="hljs-attribute">display</span>: inline-block;
   <span class="hljs-attribute">font-size</span>: <span class="hljs-number">22px</span>;
   <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;
   <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">20px</span>;
}

<span class="hljs-selector-class">.navbar-toggle</span> {
   <span class="hljs-attribute">position</span>: absolute;
   <span class="hljs-attribute">top</span>: <span class="hljs-number">10px</span>;
   <span class="hljs-attribute">right</span>: <span class="hljs-number">20px</span>;
   <span class="hljs-attribute">cursor</span>: pointer;
   <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0.8</span>);
   <span class="hljs-attribute">font-size</span>: <span class="hljs-number">24px</span>;
}

<span class="hljs-selector-class">.active</span> {
   <span class="hljs-attribute">display</span>: block;
}

<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">768px</span>) {
   <span class="hljs-selector-class">.navbar</span> {
      <span class="hljs-attribute">display</span>: flex;
      <span class="hljs-attribute">justify-content</span>: space-between;
      <span class="hljs-attribute">padding-bottom</span>: <span class="hljs-number">0</span>;
      <span class="hljs-attribute">height</span>: <span class="hljs-number">70px</span>;
      <span class="hljs-attribute">align-items</span>: center;
   }

   <span class="hljs-selector-class">.main-nav</span> {
      <span class="hljs-attribute">display</span>: flex;
      <span class="hljs-attribute">margin-right</span>: <span class="hljs-number">30px</span>;
      <span class="hljs-attribute">flex-direction</span>: row;
      <span class="hljs-attribute">justify-content</span>: flex-end;
   }

   <span class="hljs-selector-class">.main-nav</span> <span class="hljs-selector-tag">li</span> {
      <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
   }

   <span class="hljs-selector-class">.nav-links</span> {
      <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">40px</span>;
   }

   <span class="hljs-selector-class">.logo</span> {
      <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">0</span>;
   }

   <span class="hljs-selector-class">.navbar-toggle</span> {
      <span class="hljs-attribute">display</span>: none;
   }

   <span class="hljs-selector-class">.logo</span><span class="hljs-selector-pseudo">:hover</span>,
   <span class="hljs-selector-class">.nav-links</span><span class="hljs-selector-pseudo">:hover</span> {
      <span class="hljs-attribute">color</span>: <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>, <span class="hljs-number">1</span>);
   }
}
</code></pre>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> mainNav = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'js-menu'</span>);
<span class="hljs-keyword">let</span> navBarToggle = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'js-navbar-toggle'</span>);

navBarToggle.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
   mainNav.classList.toggle(<span class="hljs-string">'active'</span>);
});
</code></pre>
<iframe height="300" style="width:100%" src="https://codepen.io/Sukhjinder-arora/embed/preview/OZGomv?default-tab=result">
  See the Pen <a href="https://codepen.io/Sukhjinder-arora/pen/OZGomv">
  Responsive Navbar using flexbox and javascript</a> by Sukhjinder Arora (<a href="https://codepen.io/Sukhjinder-arora">@Sukhjinder-arora</a>)
  on <a href="https://codepen.io">CodePen</a>.
</iframe>

<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/SukhjinderArora/Responsive-Navbar-using-FlexBox">https://github.com/SukhjinderArora/Responsive-Navbar-using-FlexBox</a></div>
<h3 id="heading-read-more-about-flexbox">Read more about Flexbox:</h3>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox">https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox</a></div>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/">https://css-tricks.com/snippets/css/a-guide-to-flexbox/</a></div>
]]></content:encoded></item></channel></rss>