<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zach Snoek</title>
    <description>The latest articles on DEV Community by Zach Snoek (@zachsnoek).</description>
    <link>https://dev.to/zachsnoek</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F522064%2F62526802-6fdd-43a4-9293-8443b907c63a.jpg</url>
      <title>DEV Community: Zach Snoek</title>
      <link>https://dev.to/zachsnoek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zachsnoek"/>
    <language>en</language>
    <item>
      <title>An Overview of CSS Positioning Schemes</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Mon, 17 Jan 2022 16:30:02 +0000</pubDate>
      <link>https://dev.to/zachsnoek/an-overview-of-css-positioning-schemes-59bo</link>
      <guid>https://dev.to/zachsnoek/an-overview-of-css-positioning-schemes-59bo</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this post, we’ll learn about positioning schemes, which we can use to change an element’s position.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a post in a series about topics covered in Josh Comeau's &lt;a href="https://css-for-js.dev/" rel="noopener noreferrer"&gt;CSS for JavaScript Developers&lt;/a&gt; course. These posts will be brief, polished versions of my notes, and I'll write about new things I learned or deepen my understanding of something already familiar to me.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Static&lt;/li&gt;
&lt;li&gt;Relative&lt;/li&gt;
&lt;li&gt;Absolute&lt;/li&gt;
&lt;li&gt;Fixed&lt;/li&gt;
&lt;li&gt;Sticky&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The position property
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;position&lt;/code&gt; property allows us to specify a positioning scheme. It accepts the values: &lt;code&gt;static&lt;/code&gt;, &lt;code&gt;relative&lt;/code&gt;, &lt;code&gt;absolute&lt;/code&gt;, &lt;code&gt;fixed&lt;/code&gt;, and &lt;code&gt;sticky&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;static&lt;/code&gt; is the default value; an element with this value set is called a statically-positioned or non-positioned element. An element using a value other than &lt;code&gt;static&lt;/code&gt; is called a positioned element.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inset properties
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;position&lt;/code&gt; works with the &lt;a href="https://www.w3.org/TR/css-position-3/#coords" rel="noopener noreferrer"&gt;inset properties&lt;/a&gt; &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;right&lt;/code&gt;, &lt;code&gt;bottom&lt;/code&gt;, and &lt;code&gt;left&lt;/code&gt; to control the precise location of a positioned element.&lt;/p&gt;

&lt;p&gt;Let’s take a closer look at each of these positioning scheme values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;static&lt;/code&gt; is the default value for &lt;code&gt;position&lt;/code&gt;, and it places the element in the normal flow of the document. Inset properties do not affect the element’s position.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/PoJdRBp?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Relative
&lt;/h2&gt;

&lt;p&gt;The element gets placed in the normal flow of the document like &lt;code&gt;static&lt;/code&gt; and inset properties offset it relative to itself. This offset does not affect the layout of other elements, and the element takes up space as if it were statically positioned. The offset acts as a cosmetic effect.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/LYzJdaV?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Absolute
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;absolute&lt;/code&gt; removes the element from the normal document flow and positions it relative to its nearest positioned ancestor. If there is no positioned ancestor, the element gets positioned relative to the &lt;a href="https://www.w3.org/TR/css-display-3/#initial-containing-block" rel="noopener noreferrer"&gt;initial containing block&lt;/a&gt; (the containing block of the root &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element, a box the size and position of the viewport).&lt;/p&gt;

&lt;p&gt;No space gets made for absolutely-positioned elements in the page layout; other elements act as if they do not exist.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/ZEXMxZw?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixed
&lt;/h2&gt;

&lt;p&gt;Fixed elements behave similarly to absolutely-positioned elements, but they are always positioned relative to the initial containing block. This causes the element to appear fixed on the page, regardless of scrolling.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/ExweEqY?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Note that an element using the &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;perspective&lt;/code&gt;, and &lt;code&gt;transform&lt;/code&gt; properties or the &lt;code&gt;will-change: transform&lt;/code&gt; declaration becomes the containing block of any &lt;code&gt;fixed&lt;/code&gt; descendants, causing the &lt;code&gt;fixed&lt;/code&gt; elements to act absolutely-positioned. In other words, elements with these properties cannot have &lt;code&gt;fixed&lt;/code&gt; descendants.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sticky
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sticky&lt;/code&gt; causes the element to act like a relatively-positioned element until it reaches a threshold, at which point it becomes fixed relative to its &lt;a href="https://www.w3.org/TR/css-overflow-3/#scrollport" rel="noopener noreferrer"&gt;nearest scrollport&lt;/a&gt; (i.e., the closest ancestor that manages overflow) until its container goes out of view. Space is made for the element in the layout, even when it acts fixed.&lt;/p&gt;

&lt;p&gt;The threshold is specified by the inset properties: for example, a &lt;code&gt;sticky&lt;/code&gt; element with &lt;code&gt;top: 10px&lt;/code&gt; would be relatively-positioned until the element is 10 pixels from the top of its nearest scrollport. Once that threshold is met, the element is fixed 10 pixels from the top of its nearest scrollport.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/vYezjyZ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this example, the box sticks to the viewport but is only sticky while its container is in view:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/QWqVrpz?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Positioning in the wild
&lt;/h2&gt;

&lt;p&gt;I found it helpful to understand positioning by seeing its use in the real world. Here are a few examples of positioning types that I found.&lt;/p&gt;

&lt;h3&gt;
  
  
  Absolute: Facebook notification badge
&lt;/h3&gt;

&lt;p&gt;This notification badge on Facebook uses absolute positioning to appear above the news icon:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Fixed: StackOverflow header
&lt;/h3&gt;

&lt;p&gt;Headers commonly use fixed positioning to stick to the top of the page when the user scrolls:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41gw0533h0jzmo7bpyyh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41gw0533h0jzmo7bpyyh.gif" alt="Stack Overflow header" width="600" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sticky: iPhone product page
&lt;/h3&gt;

&lt;p&gt;Both the white “iPhone 13” header and product image on this page are sticky:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6gycnn533xqgvgr95cj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6gycnn533xqgvgr95cj.gif" alt="iPhone 13 product page" width="600" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Relative
&lt;/h3&gt;

&lt;p&gt;I couldn’t find a good example for relative positioning. Please suggest one!&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this post, connect with me on &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; to get the latest content and news from me.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=bJMEpL4rxAQ" rel="noopener noreferrer"&gt;Chris Coyier | Sticky Positioning in CSS: How it Works, What Can Break It, and Dumb Tricks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/almanac/properties/p/position/" rel="noopener noreferrer"&gt;CSS-Tricks | position&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-for-js.dev/" rel="noopener noreferrer"&gt;Josh Comeau | CSS for JavaScript Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/position" rel="noopener noreferrer"&gt;MDN | position&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Positioning" rel="noopener noreferrer"&gt;MDN | Positioning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/TR/css-position-3/" rel="noopener noreferrer"&gt;W3C | CSS Positioned Layout Module Level 3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@__itsflores?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Omar Flores&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Understanding box-sizing in CSS</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Thu, 16 Dec 2021 05:29:58 +0000</pubDate>
      <link>https://dev.to/zachsnoek/understanding-box-sizing-in-css-28bk</link>
      <guid>https://dev.to/zachsnoek/understanding-box-sizing-in-css-28bk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is a post in a series about topics covered in Josh Comeau's &lt;a href="https://css-for-js.dev/" rel="noopener noreferrer"&gt;CSS for JavaScript Developers&lt;/a&gt; course. These posts will be brief, polished versions of my notes, and I'll write about new things I learned or deepen my understanding of something already familiar to me.&lt;/p&gt;

&lt;p&gt;In this post, we'll learn about the CSS &lt;code&gt;box-sizing&lt;/code&gt; property covered in module 1 of the course.&lt;/p&gt;

&lt;h2&gt;
  
  
  The box-sizing property
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;box-sizing&lt;/code&gt; property determines how the width and height of an element are calculated. It accepts two values: &lt;code&gt;content-box&lt;/code&gt; and &lt;code&gt;border-box&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  content-box
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;content-box&lt;/code&gt; is the default value of &lt;code&gt;box-sizing&lt;/code&gt;. With this value, &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; are applied to an element's content box and do not include its padding and border.&lt;/p&gt;

&lt;p&gt;Thus, the total width of an element will be the sum of its &lt;code&gt;width&lt;/code&gt; and any horizontal padding and border. An element's height will be its &lt;code&gt;height&lt;/code&gt; plus any vertical padding and border.&lt;/p&gt;

&lt;p&gt;Take the following example:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/oNGjaBP?height=600&amp;amp;default-tab=css,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The final width and height of the &lt;code&gt;.box&lt;/code&gt; is 150 pixels: 100 + 2(20) + 2(5).&lt;/p&gt;

&lt;p&gt;We can inspect the element in the dev tools to help us visualize this:&lt;/p&gt;

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

&lt;p&gt;The content area remains 100x100 pixels and the padding and border are added around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  border-box
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;box-sizing: border-box;&lt;/code&gt;, the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; properties include the size of the element's content area, padding, and border.&lt;/p&gt;

&lt;p&gt;Here's what the previous example looks like with &lt;code&gt;border-box&lt;/code&gt; instead:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/RwLWepd?height=600&amp;amp;default-tab=css,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;And this is what the element looks like in the dev tools:&lt;/p&gt;

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

&lt;p&gt;Notice that the padding and border remain the same size, but the content area is reduced, making the final width and height 100 pixels.&lt;/p&gt;

&lt;p&gt;Here are the two examples side-by-side for comparison:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/abLvRWY?height=600&amp;amp;default-tab=css,result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Resetting border-box
&lt;/h2&gt;

&lt;p&gt;Sizing elements with &lt;code&gt;content-box&lt;/code&gt; is unintuitive because it requires us to subtract or add values to get the desired &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt;. Working with &lt;code&gt;border-box&lt;/code&gt; is more natural: if we set an element's &lt;code&gt;width&lt;/code&gt; to &lt;code&gt;500px&lt;/code&gt; then we know its final width will be 500 pixels.&lt;/p&gt;

&lt;p&gt;You can use &lt;code&gt;border-box&lt;/code&gt; sizing for all elements with the following CSS reset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;*,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Test your knowledge
&lt;/h2&gt;

&lt;p&gt;Check your understanding of &lt;code&gt;box-sizing&lt;/code&gt; by figuring out the width and height of each &lt;code&gt;.box&lt;/code&gt; in the following snippets.&lt;/p&gt;

&lt;h3&gt;
  
  
  #1
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;dotted&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is the total height of this &lt;code&gt;.box&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;
  Click to reveal answer
  &lt;p&gt;100 pixels. The content area is reduced to include the border. &lt;/p&gt;

&lt;/p&gt;

&lt;h3&gt;
  
  
  #2
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is the total width and height of this &lt;code&gt;.box&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;
  Click to reveal answer
  &lt;p&gt;60x60 pixels. The content area does not include the padding, so we add that to the width and height. &lt;/p&gt;

&lt;/p&gt;

&lt;h3&gt;
  
  
  #3
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;content-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="nb"&gt;dashed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is the content area of this &lt;code&gt;.box&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;
  Click to reveal answer
  &lt;p&gt;30x50 pixels. &lt;/p&gt;

&lt;/p&gt;

&lt;h3&gt;
  
  
  #4
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is the content area of this &lt;code&gt;.box&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;
  Click to reveal answer
  &lt;p&gt;84x84 pixels: 100 - 2(7)- 2(1). &lt;/p&gt;

&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;box-sizing&lt;/code&gt; controls how the width and height of an element are calculated. &lt;code&gt;content-box&lt;/code&gt; is the default value and &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; are applied to an element's content area. &lt;code&gt;border-box&lt;/code&gt; is more intuitive; the content area of an element is reduced to include any padding and border.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this post, connect with me on &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://css-for-js.dev/" rel="noopener noreferrer"&gt;Josh W. Comeau | CSS for JavaScript Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing" rel="noopener noreferrer"&gt;MDN | box-sizing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/learn/css/box-model/" rel="noopener noreferrer"&gt;web.dev | Box Model&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@fakurian?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Fakurian Design&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Four tips for staying motivated while learning</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Fri, 26 Nov 2021 22:11:40 +0000</pubDate>
      <link>https://dev.to/zachsnoek/four-tips-for-staying-motivated-while-learning-473e</link>
      <guid>https://dev.to/zachsnoek/four-tips-for-staying-motivated-while-learning-473e</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Software engineering is a field that is regularly changing. Thus, developers must be continual learners to stay sharp.&lt;/p&gt;

&lt;p&gt;However, motivating yourself to learn and creating a lasting habit can be difficult, especially if you're self-studying outside of school or work.  Below are four techniques that I use to stay motivated while learning.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick reference
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Set deadlines&lt;/li&gt;
&lt;li&gt;Gamify&lt;/li&gt;
&lt;li&gt;Spice it up&lt;/li&gt;
&lt;li&gt;Identify the end goal&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Set deadlines
&lt;/h2&gt;

&lt;p&gt;Learning without structure can feel like an endless task with no end in sight; it's often nice to have a sense of progress. I've found that artificial deadlines give me something to work toward and cleanly mark progress.&lt;/p&gt;

&lt;p&gt;Here are some examples of deadlines you could set for yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I will study Python for 30 minutes by the end of the day&lt;/li&gt;
&lt;li&gt;I will complete one module of my online JavaScript course by Friday every week&lt;/li&gt;
&lt;li&gt;I will finish two projects by the end of the month&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure to create manageable deadlines; experiment until you find something right for you. You may want to try a large interval at first and narrow it down until you find the sweet spot.&lt;/p&gt;

&lt;p&gt;For example, when I first started blogging, I wanted to publish bi-weekly. I quickly realized that writing and researching a quality post in two weeks wasn't possible for me, so I changed to a monthly schedule.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Gamify
&lt;/h2&gt;

&lt;p&gt;Deadlines aren't for everyone: you might have better luck incentivizing yourself through gamification.&lt;/p&gt;

&lt;p&gt;For instance, you could implement a basic point system in which you earn a point every day you study SQL. You can use 14 points to treat yourself to a small meal or pay yourself five dollars. Or, you could reward yourself some other way when you've done something five consecutive days.&lt;/p&gt;

&lt;p&gt;I find the most motivation from the &lt;a href="https://lifehacker.com/jerry-seinfelds-productivity-secret-281626" rel="noopener noreferrer"&gt;Seinfeld method&lt;/a&gt;. The idea is that every day you do something––learning in some way, in our case––you put a red X through the day on a calendar. The more days you add X's, the longer the chain of X's gets; your goal is to "not break the chain." This method is essentially point-earning and provides an incentive for showing up consistently.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Spice it up
&lt;/h2&gt;

&lt;p&gt;I've found it helpful to vary how I study the material. I find that learning through one medium can be tiring after a while. Temporarily switching the medium motivates me to keep learning.&lt;/p&gt;

&lt;p&gt;If I'm learning one topic, I find a preferred, primary medium for studying it––typically text. I'll then augment this material with other media such as YouTube videos and podcasts.&lt;/p&gt;

&lt;p&gt;For example, if I'm learning about prototypes in JavaScript, I'll spend most of my time reading Mozilla documentation or other articles. When I've absorbed that material, I'll watch various YouTube videos about prototypes and then try to write code and build something that uses them.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Identify the end goal
&lt;/h2&gt;

&lt;p&gt;Finally, learn with a clear goal in mind, and use this goal to remind yourself why you're learning.&lt;/p&gt;

&lt;p&gt;Why are you learning? Maybe you're preparing for a career change that will boost your income. Or perhaps you're &lt;a href="https://www.swyx.io/learn-in-public/" rel="noopener noreferrer"&gt;learning in public&lt;/a&gt; to help others and gain credibility. (Upward mobility has been a good impetus for me.)&lt;/p&gt;

&lt;p&gt;Remind yourself of this goal frequently: write it down on a sticky note attached to your computer or set a reminder on your phone; whatever is visible to you.&lt;/p&gt;

&lt;p&gt;Most importantly, find a goal that motivates you when you're the most unmotivated. A resilient objective can carry you through the periods when you'd rather watch Netflix or stop learning.&lt;/p&gt;

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

&lt;p&gt;All of these methods might not work for you, but hopefully, you've been able to pick up something helpful. Let me know in the comments if there's a motivation technique you use that I missed!&lt;/p&gt;




&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this post, connect with me on &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>motivation</category>
    </item>
    <item>
      <title>CSS em and rem units #CSSforJS</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Thu, 04 Nov 2021 03:03:30 +0000</pubDate>
      <link>https://dev.to/zachsnoek/css-em-and-rem-units-cssforjs-5697</link>
      <guid>https://dev.to/zachsnoek/css-em-and-rem-units-cssforjs-5697</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is my first post in a series about topics covered in Josh Comeau's &lt;a href="https://css-for-js.dev/" rel="noopener noreferrer"&gt;CSS for JavaScript Developers&lt;/a&gt; course. These posts will be brief, polished versions of my notes. I'll write about new things I learned or deepen my understanding of something already familiar to me.&lt;/p&gt;

&lt;p&gt;In this post, we'll explore the &lt;code&gt;em&lt;/code&gt; and &lt;code&gt;rem&lt;/code&gt; units in CSS, covered in module 0 of the course.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ems
&lt;/h2&gt;

&lt;p&gt;An &lt;code&gt;em&lt;/code&gt; is a unit relative to the &lt;code&gt;font-size&lt;/code&gt; of the current element. When used for the &lt;code&gt;font-size&lt;/code&gt; property, an &lt;code&gt;em&lt;/code&gt; is relative to the &lt;code&gt;font-size&lt;/code&gt; of the &lt;em&gt;parent&lt;/em&gt; element.&lt;/p&gt;

&lt;p&gt;For example, if an element has a &lt;code&gt;font-size&lt;/code&gt; of &lt;code&gt;16px&lt;/code&gt; and &lt;code&gt;padding&lt;/code&gt; of &lt;code&gt;2em&lt;/code&gt;, the element's &lt;code&gt;padding&lt;/code&gt; will be 32 pixels (16 x 2):&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/VwzPgjG?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If an element has a &lt;code&gt;font-size&lt;/code&gt; of &lt;code&gt;16px&lt;/code&gt; and its child has a &lt;code&gt;font-size&lt;/code&gt; of &lt;code&gt;1.5em&lt;/code&gt;, the child's &lt;code&gt;font-size&lt;/code&gt; will be 24 pixels (16 x 1.5):&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/abypXWE?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If the element's  &lt;code&gt;font-size&lt;/code&gt; is not set, the closest ancestor with a &lt;code&gt;font-size&lt;/code&gt; gets used. Note that browsers have a default font size of 16 pixels out of the box, so &lt;code&gt;1em&lt;/code&gt; is generally equal to 16 pixels.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;em&lt;/code&gt;s are useful when scaling some property with the element's &lt;code&gt;font-size&lt;/code&gt;. Consider the following &lt;code&gt;.box&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create small, medium, and large boxes with these same proportions, we can alter the  &lt;code&gt;font-size&lt;/code&gt; of each &lt;code&gt;.box&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/porRGpR?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  The compounding problem
&lt;/h3&gt;

&lt;p&gt;Because &lt;code&gt;em&lt;/code&gt;s are relative, the value of an &lt;code&gt;em&lt;/code&gt; in descendant elements can compound. This can cause unexpected layout changes when a font size change ripples through descendant elements. For instance, if an element has a &lt;code&gt;font-size&lt;/code&gt; of &lt;code&gt;2em&lt;/code&gt; and its child has a &lt;code&gt;font-size&lt;/code&gt; of &lt;code&gt;1.5em&lt;/code&gt;, the child's font size is 48 pixels (16 x 2 x 1.5):&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/mdMRZjO?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Rems
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;rem&lt;/code&gt;, short for "root em," is like an &lt;code&gt;em&lt;/code&gt;, but its value is relative to the root &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; tag. So, if the root &lt;code&gt;font-size&lt;/code&gt; is 16 pixels, a value of &lt;code&gt;2rem&lt;/code&gt; is 32 pixels at every level in the DOM:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/wvqgLLy?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rem&lt;/code&gt;s are always relative to the root element, so there isn't an issue with compounding. This makes them more predictable and consistent than &lt;code&gt;em&lt;/code&gt;s:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/oNeBrKx?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;We can use &lt;code&gt;rem&lt;/code&gt;s to scale values globally by only changing the root &lt;code&gt;font-size&lt;/code&gt;. The following &lt;code&gt;article&lt;/code&gt; has many font sizes specified in &lt;code&gt;rem&lt;/code&gt;s, and we can use a media query to change all the sizes by setting the root &lt;code&gt;font-size&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/zachsnoek/embed/MWvJNYx?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Em and rem a11y benefits
&lt;/h2&gt;

&lt;p&gt;Both &lt;code&gt;em&lt;/code&gt;s and &lt;code&gt;rem&lt;/code&gt;s help make our sites more accessible by respecting the user's default font size, set in their browser's settings. Using a fixed unit such as &lt;code&gt;px&lt;/code&gt; will override this setting, but &lt;code&gt;em&lt;/code&gt; and &lt;code&gt;rem&lt;/code&gt; will scale it. This makes &lt;code&gt;rem&lt;/code&gt;s particularly good for typography because we can scale the user's font size preference globally without &lt;code&gt;em&lt;/code&gt; interference.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;em&lt;/code&gt; and &lt;code&gt;rem&lt;/code&gt; are relative units. An &lt;code&gt;em&lt;/code&gt; is generally relative to the current element's &lt;code&gt;font-size&lt;/code&gt;; when used for the &lt;code&gt;font-size&lt;/code&gt; property, it's relative to its parent's &lt;code&gt;font-size&lt;/code&gt;. A &lt;code&gt;rem&lt;/code&gt; is relative to the root &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element's &lt;code&gt;font-size&lt;/code&gt;, which is usually 16 pixels. Take caution when using &lt;code&gt;em&lt;/code&gt;s because of their compounding effect; &lt;code&gt;rem&lt;/code&gt;s are more predictable and increase accessibility by respecting the user's default font size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! If you enjoyed this post, connect with me on &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://css-for-js.dev/" rel="noopener noreferrer"&gt;Josh Comeau | CSS for JavaScript Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=_-aDOAMmDHI" rel="noopener noreferrer"&gt;Kevin Powell | CSS em and rem explained #CSS #responsive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units" rel="noopener noreferrer"&gt;MDN | CSS values and units&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" rel="noopener noreferrer"&gt;MDN | font-size&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>cssforjs</category>
    </item>
    <item>
      <title>How to build an HTTP-triggered function with Azure Functions</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Sat, 09 Oct 2021 05:25:54 +0000</pubDate>
      <link>https://dev.to/zachsnoek/how-to-build-an-http-triggered-function-with-azure-functions-23eg</link>
      <guid>https://dev.to/zachsnoek/how-to-build-an-http-triggered-function-with-azure-functions-23eg</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Serverless computing is an architecture that allows developers to deploy code without provisioning and maintaining the backend infrastructure to support it. By abstracting servers, it allows us to focus on the code that we write and think less about hardware.&lt;/p&gt;

&lt;p&gt;There are many serverless solutions from cloud computing providers such as Amazon Web Services, Google Cloud, and Microsoft Azure. In this tutorial, I'll show you how to create a serverless function with Azure Functions that's triggered with an HTTP request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Node.js installed&lt;/li&gt;
&lt;li&gt;  An Azure account (you can create an account for free &lt;a href="https://azure.microsoft.com/en-us/free/?v=a&amp;amp;adobe_mc_sdid=SDID%3D46A1292C024EC08B-2622DAEB632EB5D7%7CMCORGID%3DEA76ADE95776D2EC7F000101%40AdobeOrg%7CTS%3D1633407500" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you don't have one)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll show you how to write a function in TypeScript, so you should be familiar with TypeScript or JavaScript. Additionally, you should have experience with NPM, web APIs, and basic UNIX commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Azure Functions?
&lt;/h2&gt;

&lt;p&gt;Azure Functions is a serverless service from Microsoft that allows us to write blocks of code called functions that run in response to an event, such as an HTTP request or IoT event. Instead of worrying about server operating systems and hardware that host our code, Azure handles the provisioning and maintenance of the hardware and infrastructure needed for us––all we do is write the function logic and deploy it.&lt;/p&gt;

&lt;p&gt;Functions will automatically scale up and down based on demand, and Azure will only bill us for the time that our code is executed. This can help us save costs if our application has significant downtime: with traditional hosting, we would have to pay for a server that is always online.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Azure packages for local development
&lt;/h2&gt;

&lt;p&gt;To develop and deploy functions locally, we need to download two packages from Azure. Run the following commands to install Azure Functions Core Tools, a set of tools for developing and testing functions locally (installation instructions for Windows and Linux can be found &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=v3%2Cwindows%2Ccsharp%2Cportal%2Cbash%2Ckeda#install-the-azure-functions-core-tools" rel="noopener noreferrer"&gt;here&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap azure/functions
brew &lt;span class="nb"&gt;install &lt;/span&gt;azure-functions-core-tools@3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can ensure that Core Tools is installed by running &lt;code&gt;func --version&lt;/code&gt; which should output a version number like &lt;code&gt;3.x.x&lt;/code&gt;. Next, install Azure CLI (installation instructions for Windows and Linux can be found &lt;a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli" rel="noopener noreferrer"&gt;here&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;azure-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Azure CLI provides commands for working with Azure resources and allows us to deploy our function to Azure.&lt;/p&gt;

&lt;p&gt;Confirm that the CLI has been installed and sign in to Azure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the Azure CLI is installed correctly, you'll be redirected to a page where you can sign in to your Azure account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the local function project
&lt;/h2&gt;

&lt;p&gt;Now that we have the required packages installed, let's create a function project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;func init azure-tutorial &lt;span class="nt"&gt;--typescript&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;azure-tutorial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a local function project called &lt;code&gt;azure-tutorial&lt;/code&gt; with some default configuration files. A function project contains one or more functions that share the same configuration.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;ls&lt;/code&gt; will show the following files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;azure-tutorial/
├─ host.json
├─ local.settings.json
├─ package.json
├─ tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's briefly explore each of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;host.json:&lt;/strong&gt; Contains global configuration options shared by all of the functions in a function project. We won't be modifying the defaults in this tutorial, so you can read the &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-host-json" rel="noopener noreferrer"&gt;host.json reference&lt;/a&gt; from Microsoft for more information.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;local.settings.json:&lt;/strong&gt; Stores local app and development tool settings. App settings and secrets, such as API keys and connection strings, can be added to the &lt;code&gt;Values&lt;/code&gt; object and read in the function as environment variables. See the &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-develop-local#local-settings-file" rel="noopener noreferrer"&gt;Microsoft docs&lt;/a&gt; for more information about the other supported local settings.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;package.json:&lt;/strong&gt; Contains the project's configuration. Note that we're given a &lt;code&gt;build&lt;/code&gt; script to compile the TypeScript, a &lt;code&gt;prestart&lt;/code&gt; script that runs &lt;code&gt;build&lt;/code&gt;, and a &lt;code&gt;start&lt;/code&gt; script that runs the function locally.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;tsconfig.json:&lt;/strong&gt; Default TypeScript compiler options.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create the function from a template
&lt;/h2&gt;

&lt;p&gt;Throughout this tutorial, we'll create a function named &lt;code&gt;CreateUser&lt;/code&gt; that imitates a user registration endpoint. It will be triggered by a POST request containing &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; fields in the request body. Run the following command to scaffold a &lt;code&gt;CreateUser&lt;/code&gt; function from the HTTP trigger template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;func new &lt;span class="nt"&gt;--name&lt;/span&gt; CreateUser &lt;span class="nt"&gt;--template&lt;/span&gt; &lt;span class="s2"&gt;"HTTP trigger"&lt;/span&gt; &lt;span class="nt"&gt;--authlevel&lt;/span&gt; &lt;span class="s2"&gt;"anonymous"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;ls&lt;/code&gt; again will show a new function directory called &lt;code&gt;CreateUser&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;azure-tutorial/
├─ CreateUser/
│  ├─ function.json
│  ├─ index.ts
├─ host.json
├─ local.settings.json
├─ package.json
├─ tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This directory contains everything we need for a function: a &lt;code&gt;function.json&lt;/code&gt; configuration file and the function's code. Open up your &lt;code&gt;azure-tutorial&lt;/code&gt; directory in a text editor so we can start exploring these function files.&lt;/p&gt;

&lt;h3&gt;
  
  
  function.json
&lt;/h3&gt;

&lt;p&gt;A function must have a function.json file, which contains its configuration information such as the trigger type and bindings. A function has exactly one &lt;strong&gt;trigger,&lt;/strong&gt; which is an event that causes it to run.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;binding&lt;/strong&gt; defines how we get data into our function or send it out of our function––it connects resources to the function. Bindings are added to the &lt;code&gt;bindings&lt;/code&gt; array. For example, our function contains the following HTTP trigger input binding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "authLevel": "Anonymous",
    "type": "httpTrigger",
    "direction": "in",
    "name": "req",
    "methods": ["get", "post"],
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;direction&lt;/code&gt; defines it to be an input binding, and &lt;code&gt;name&lt;/code&gt; defines the name of the parameter passed to the function that contains the HTTP request data. Note that we've specified an &lt;code&gt;anonymous&lt;/code&gt; authorization level to allow it to be triggered by anyone. You can read more about authorization levels in the &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=csharp#configuration" rel="noopener noreferrer"&gt;Microsoft docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Similarly, we have an output binding that defines our output data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "type": "http",
    "direction": "out",
    "name": "res"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;name&lt;/code&gt; defines the property name on the context object returned from our function that contains the response data, which we will see shortly.&lt;/p&gt;

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

&lt;p&gt;This file exports a function named &lt;code&gt;httpTrigger&lt;/code&gt; that Azure runs when the function is triggered. The HTTP request object is the &lt;code&gt;req&lt;/code&gt; parameter (defined by the input binding's &lt;code&gt;name&lt;/code&gt; property in &lt;code&gt;function.json&lt;/code&gt;), and a context object is passed through the &lt;code&gt;context&lt;/code&gt; parameter when the function is run.&lt;/p&gt;

&lt;p&gt;The default function code provided for us allows us to specify a name in the query parameters or request body. When run, it creates a response message and sets the response on the context object's &lt;code&gt;res&lt;/code&gt; property, which was defined in &lt;code&gt;function.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the default function locally
&lt;/h2&gt;

&lt;p&gt;The boilerplate that we've just explored is a working function that we can make requests to locally. Let's ensure that everything is working properly by running it and making a request to its &lt;code&gt;CreateUser&lt;/code&gt; endpoint.&lt;/p&gt;

&lt;p&gt;In the root directory, install the project's NPM dependencies:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We can now start the function with &lt;code&gt;npm start&lt;/code&gt;, which will compile the TypeScript and start a local server. This command should show the following output:&lt;br&gt;
&lt;/p&gt;

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

        CreateUser: [GET,POST] http://localhost:7071/api/CreateUser
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, HTTP-triggered functions are available at the &lt;code&gt;/api/&amp;lt;function name&amp;gt;&lt;/code&gt; endpoint. Make a test GET request to our function with the following &lt;code&gt;curl&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:7071/api/CreateUser?name&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This request should return a response like "Hello, Zach. This HTTP triggered function executed successfully." We can also test out the POST request with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:7071/api/CreateUser &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "&amp;lt;Your name&amp;gt;"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! You've created a local function project with a working function. Let's see what else we can do with our HTTP trigger by updating it to do something a little more useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring the function to accept POST requests
&lt;/h2&gt;

&lt;p&gt;By default, our HTTP input trigger accepts both GET and POST methods, but our &lt;code&gt;CreateUser&lt;/code&gt; function should only allow a POST request. Let's fix this by removing the GET method from the input binding's &lt;code&gt;method&lt;/code&gt; property, which is an array containing the function's allowed HTTP methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bindings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"authLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anonymous"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"httpTrigger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"req"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"methods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"post"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While we're here, let's make the name of our function's endpoint RESTful and name it &lt;code&gt;/api/users&lt;/code&gt; instead of &lt;code&gt;/api/CreateUser&lt;/code&gt;. We can specify a custom name by setting the &lt;code&gt;route&lt;/code&gt; property of the input trigger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bindings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"authLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anonymous"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"httpTrigger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"req"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"methods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"post"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"users"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After restarting the function, you should see output to indicate that the &lt;code&gt;CreateUser&lt;/code&gt; function is triggered by the &lt;code&gt;/api/users&lt;/code&gt; endpoint now and only accepts POST requests:&lt;br&gt;
&lt;/p&gt;

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

        CreateUser: [POST] http://localhost:7071/api/users
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Writing and testing the function
&lt;/h2&gt;

&lt;p&gt;We've got our function bindings configured, so let's replace the generated function with our own code. As mentioned earlier, our function will take in a &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; in the request body. We'll also want to return the created user object as JSON and send a &lt;code&gt;201&lt;/code&gt; response code to indicate that a user was created.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;index.ts&lt;/code&gt;, rename the function from &lt;code&gt;httpTrigger&lt;/code&gt; to &lt;code&gt;createUser&lt;/code&gt; and delete all of the code within the function body. Your file should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AzureFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@azure/functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AzureFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpRequest&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO: Implement&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Next, add the following code to the function body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// In real life, we'd add the user object to our database here&lt;/span&gt;

&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We simply construct a user object from the request body and return that object in the response body with the appropriate status code and header. Restart the function and make a POST request with a username and password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:7071/api/users &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"username": "foo", "password": "bar"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response will have &lt;code&gt;{"username": "foo", "password": "bar"}&lt;/code&gt; in the body and a &lt;code&gt;201&lt;/code&gt; status code.&lt;/p&gt;

&lt;p&gt;In real life, though, we'd probably want to add some request validation that requires the caller to provide both a username and password. If the user provides invalid input, we should return a &lt;code&gt;400&lt;/code&gt; status code and a helpful error message. Replace the function body with this updated implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;responseStatus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;responseStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;responseBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;responseStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;responseBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Missing username or password.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responseStatus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;responseBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, restart the function and make a request without a username or password. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:7071/api/users &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"username": "foo"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get a &lt;code&gt;400&lt;/code&gt; response code and a response containing &lt;code&gt;{"error": "Missing username or password"}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's it for the function. Now, let's get ready to deploy the function to Azure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Azure resources for deployment
&lt;/h2&gt;

&lt;p&gt;To deploy our function, we need to create an Azure resource group, storage account, and function app. A resource group is a container for Azure resources, and a storage account stores a function's state, code, and configuration files.&lt;/p&gt;

&lt;p&gt;You'll want to create the resource group and storage account in a region that's close to you to reduce latency. You can list the regions available to you by running &lt;code&gt;az account list-locations&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az account list-locations &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"[].{Region:name}"&lt;/span&gt; &lt;span class="nt"&gt;--out&lt;/span&gt; table | less
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For instance, I live in Washington, United States, so I'll use the &lt;code&gt;westus2&lt;/code&gt; location.&lt;/p&gt;

&lt;p&gt;The next few commands require us to repeat a lot of configuration information, so set the following environment variables that we can use later on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your region&amp;gt;                       &lt;span class="c"&gt;# The region you chose above&lt;/span&gt;
&lt;span class="nv"&gt;RESOURCE_GROUP_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;azure-tutorial-rg      &lt;span class="c"&gt;# The name of the resource group&lt;/span&gt;
&lt;span class="nv"&gt;STORAGE_ACCOUNT_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your unique name&amp;gt;    &lt;span class="c"&gt;# The name of the storage account&lt;/span&gt;
&lt;span class="nv"&gt;FUNCTION_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your unique name&amp;gt;           &lt;span class="c"&gt;# The name of the function app in Azure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a resource group with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az group create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$RESOURCE_GROUP_NAME&lt;/span&gt; &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nv"&gt;$REGION&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create the storage account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage account create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$STORAGE_ACCOUNT_NAME&lt;/span&gt; &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nv"&gt;$REGION&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$RESOURCE_GROUP_NAME&lt;/span&gt; &lt;span class="nt"&gt;--sku&lt;/span&gt; Standard_LRS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that storage account names need to be globally unique; an ambiguous error message could mean that the storage name is unavailable. You can check if your name is available by running &lt;code&gt;az storage account check-name --name $STORAGE_ACCOUNT_NAME&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we can create our function app in Azure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az functionapp create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="nv"&gt;$FUNCTION_NAME&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; &lt;span class="nv"&gt;$RESOURCE_GROUP_NAME&lt;/span&gt; &lt;span class="nt"&gt;--storage-account&lt;/span&gt; &lt;span class="nv"&gt;$STORAGE_ACCOUNT_NAME&lt;/span&gt; &lt;span class="nt"&gt;--consumption-plan-location&lt;/span&gt; &lt;span class="nv"&gt;$REGION&lt;/span&gt; &lt;span class="nt"&gt;--runtime&lt;/span&gt; node &lt;span class="nt"&gt;--runtime-version&lt;/span&gt; 12 &lt;span class="nt"&gt;--functions-version&lt;/span&gt; 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like storage accounts, function names need to be unique in Azure.&lt;/p&gt;

&lt;p&gt;When the command completes, you can ensure that the function was created by listing your function apps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az functionapp list &lt;span class="nt"&gt;--out&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploying the function to Azure
&lt;/h2&gt;

&lt;p&gt;We're now ready to deploy our function! First, create a production build of our app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build:production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now deploy the function with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;func azure functionapp publish &lt;span class="nv"&gt;$FUNCTION_NAME&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the deployment succeeds, you should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
Functions in &amp;lt;function name&amp;gt;:
    CreateUser - [httpTrigger]
        Invoke url: https://&amp;lt;function name&amp;gt;.azurewebsites.net/api/users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "Invoke url" in the output is the URL that triggers our function. Copy the URL and test out the requests we made locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;invoke URL&amp;gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"username": "foo", "password": "bar"}'&lt;/span&gt; &lt;span class="c"&gt;# returns a 201&lt;/span&gt;
curl &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;invoke URL&amp;gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"username": "foo"}'&lt;/span&gt; &lt;span class="c"&gt;# returns a 400&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Congrats! You've created and deployed your own function to Azure. Now that you've used an HTTP trigger, I encourage you to check out the &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/" rel="noopener noreferrer"&gt;Azure Functions documentation&lt;/a&gt; and explore other types of function triggers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this post, connect with me on &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://github.com/marcduiker/azure-functions-university/blob/main/lessons/deployment/deployment-lesson.md" rel="noopener noreferrer"&gt;Azure Functions University | Deployment to Azure&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference" rel="noopener noreferrer"&gt;Microsoft | Azure Functions developer guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=javascript" rel="noopener noreferrer"&gt;Microsoft | Azure Functions HTTP trigger&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings?tabs=javascript" rel="noopener noreferrer"&gt;Microsoft | Azure Functions triggers and bindings concepts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-develop-local#local-settings-file" rel="noopener noreferrer"&gt;Microsoft | Code and test Azure Functions locally&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-typescript?tabs=azure-cli%2Cbrowser#invoke-the-function-on-azure" rel="noopener noreferrer"&gt;Microsoft | Quickstart: Create a TypeScript function in Azure from the command line&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=v3%2Cwindows%2Cnode%2Cportal%2Cbash%2Ckeda#local-settings" rel="noopener noreferrer"&gt;Microsoft | Work with Azure Functions Core Tools&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.youtube.com/watch?v=UFxQhszT450" rel="noopener noreferrer"&gt;Microsoft Azure | Go serverless: Event-driven applications with Azure Functions | Azure Friday&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.youtube.com/watch?v=zYb5sVQgUN4" rel="noopener noreferrer"&gt;Serverless on Azure | Azure Functions University - HTTP (TypeScript)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>azure</category>
      <category>serverless</category>
      <category>tutorial</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Build a meme generator with JavaScript and Fabric.js</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Wed, 01 Sep 2021 21:16:39 +0000</pubDate>
      <link>https://dev.to/zachsnoek/build-a-meme-generator-with-javascript-and-fabric-js-7o8</link>
      <guid>https://dev.to/zachsnoek/build-a-meme-generator-with-javascript-and-fabric-js-7o8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Memes are great: We can use them for humor, cryptocurrency, and even for learning JavaScript! In this tutorial, I'll show you how to make a meme generator with JavaScript and Fabric.js that lets you customize templates from three popular memes: &lt;a href="https://en.wikipedia.org/wiki/Doge_(meme)" rel="noopener noreferrer"&gt;Doge&lt;/a&gt;, &lt;a href="https://knowyourmeme.com/memes/daily-struggle" rel="noopener noreferrer"&gt;Daily Struggle&lt;/a&gt;, and &lt;a href="https://knowyourmeme.com/memes/philosoraptor" rel="noopener noreferrer"&gt;Philosoraptor&lt;/a&gt;. Users will be able to select one of the templates, edit and move the text fields, then download their creation. Here's what it looks like in action:&lt;/p&gt;

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

&lt;p&gt;At the end of this tutorial, I'll give you some ways that you can extend this project and make it your own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;This is a JavaScript-focused tutorial; you should have experience with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic HTML and CSS&lt;/li&gt;
&lt;li&gt;JavaScript fundamentals&lt;/li&gt;
&lt;li&gt;Basic DOM manipulation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having some knowledge of the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element and the Canvas API is helpful but not required. I would recommend giving the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API" rel="noopener noreferrer"&gt;MDN Canvas API docs&lt;/a&gt; a glance before continuing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Fabric.js?
&lt;/h2&gt;

&lt;p&gt;The HTML &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element and Canvas API allow us to draw graphics in the browser with JavaScript. However, the Canvas API is low-level and can be difficult to work with. This tutorial will introduce Fabric.js (Fabric), which is one of the many libraries that make working with the Canvas API easier. Our meme generator will use Fabric to render the template images and text fields on the canvas, and to export it to an image that we can download.&lt;/p&gt;

&lt;p&gt;One benefit of Fabric is its object model for interacting with canvas elements. For instance, this is how we could create a rectangle using the native API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fillStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the native API, we manipulate the canvas through a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D" rel="noopener noreferrer"&gt;context object&lt;/a&gt; representing the entire canvas. With Fabric, we operate on objects within the canvas. Here's how we would create the same rectangle and add it to the canvas with Fabric:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;fabric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;fabric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Rect&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fabric's API is easier to use and understand, even in this simple example. Additionally, Fabric provides many features that the Canvas API lacks, such as additional built-in shapes, an interactivity layer, and object grouping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloning the starter code
&lt;/h2&gt;

&lt;p&gt;To keep this tutorial focused on JavaScript and Fabric, I've created a &lt;code&gt;starter-code&lt;/code&gt; branch in the tutorial's &lt;a href="https://github.com/zachsnoek/meme-generator" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; that contains the HTML and CSS for the project, as well as the meme template data. The completed project can be found on the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;Run the following commands to clone the repository, check out the &lt;code&gt;starter-code&lt;/code&gt; branch, and move into the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone -b starter-code https://github.com/zachsnoek/meme-generator.git
$ cd meme-generator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go ahead and open the new &lt;code&gt;meme-generator&lt;/code&gt; directory in your text editor. You should see the following directories and files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;meme-generator/
├─ css/
│  ├─ styles.css
├─ img/
│  ├─ placeholder.jpg
├─ js/
│  ├─ meme-templates.js
├─ index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Live Server
&lt;/h3&gt;

&lt;p&gt;I recommend using &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt; as your text editor with the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer" rel="noopener noreferrer"&gt;Live Server&lt;/a&gt; extension when working through this tutorial. You can simply open &lt;code&gt;index.html&lt;/code&gt; and hit &lt;code&gt;alt+L&lt;/code&gt; on Windows or &lt;code&gt;cmd+L&lt;/code&gt; on macOS to start a local development server, and the server will automatically reload whenever a change in the project has been made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring the starter code
&lt;/h2&gt;

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

&lt;p&gt;This is our simple HTML file for the project. The &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; with the &lt;code&gt;template-selectors&lt;/code&gt; ID is where the template selector buttons––the buttons that allow you to switch templates––will be rendered by our JavaScript. We'll add an event listener to the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; so that our templates can be downloaded, and the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element is where we'll render our templates.&lt;/p&gt;

&lt;h3&gt;
  
  
  css/styles.css
&lt;/h3&gt;

&lt;p&gt;The styles for this project are pretty simple, but I do want to point out the &lt;code&gt;.selected-template&lt;/code&gt; CSS class. When a template selector button is clicked, we'll apply this class to the button to indicate the currently selected template.&lt;/p&gt;

&lt;h3&gt;
  
  
  img/
&lt;/h3&gt;

&lt;p&gt;This directory will contain all of the meme background images for our templates. I'll leave it up to you to download the images and place them in &lt;code&gt;img&lt;/code&gt; with the filenames listed below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pds.exblog.jp/pds/1/201002/12/90/a0126590_22301391.jpg" rel="noopener noreferrer"&gt;doge.jpg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://i.imgflip.com/sxycb.jpg?a452736" rel="noopener noreferrer"&gt;daily-struggle.png&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://imgflip.com/s/meme/Philosoraptor.jpg" rel="noopener noreferrer"&gt;philosoraptor.jpg&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(&lt;code&gt;placeholder.jpg&lt;/code&gt; is not needed; you can safely delete this image.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring the meme templates
&lt;/h2&gt;

&lt;p&gt;When our meme generator is loaded and when we select a template, we will render a template on the canvas. Each template is a JavaScript object that contains metadata about the meme, such as the background image and text fields. Fabric will use this information to render the template on the canvas. All of the templates are exported as an array from &lt;code&gt;js/meme-templates.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Doge&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;backgroundUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;img/doge.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;640&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;480&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;textFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Wow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Comic Sans MS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the properties in our template objects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: The template's display name shown in the selector.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backgroundUrl&lt;/code&gt;: The path to the template's background image. We store all of the images locally in &lt;code&gt;img&lt;/code&gt; for this tutorial.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;width&lt;/code&gt;: The width of the image in pixels. This is used for setting the canvas' size.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;height&lt;/code&gt;: The height of the image in pixels. This is used for setting the canvas' size.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;textFields&lt;/code&gt;: An array containing objects that describe the individual text fields to render. &lt;code&gt;text&lt;/code&gt; is the text to display in the field the the other properties are used to style the text.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Accessing the canvas with Fabric.js
&lt;/h2&gt;

&lt;p&gt;Now that we understand the provided code and templates, let's get started by accessing the canvas. We'll first need to create a JavaScript file for all of our meme generator's code. Create a file in &lt;code&gt;js&lt;/code&gt; named &lt;code&gt;index.js&lt;/code&gt;, and add a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag in &lt;code&gt;index.html&lt;/code&gt; to refer to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./js/index.js"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to load Fabric from the CDN by adding another &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag above the one we just added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script
        &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;
        &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.min.js"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./js/index.js"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can create a &lt;code&gt;fabric.Canvas&lt;/code&gt; object to access the canvas. Add the following line to the top of &lt;code&gt;index.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;fabric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;fabric.Canvas&lt;/code&gt; is a wrapper around the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element and it manages all of the Fabric objects on the canvas. It also allows us to configure canvas settings such as the size and background color.&lt;/p&gt;

&lt;p&gt;Let's make sure we've accessed the canvas properly by adding the following code to set the canvas' width, height, and background color:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBackgroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you open &lt;code&gt;index.html&lt;/code&gt; in your browser or start Live Server, you should see a square, red canvas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering a meme template
&lt;/h2&gt;

&lt;p&gt;We've verified that we can access the canvas using Fabric, so let's create a function called &lt;code&gt;renderTemplate&lt;/code&gt; that will render a meme template on the canvas.  When a selector is clicked, we'll pass the corresponding template's metadata (from &lt;code&gt;meme-templates.js&lt;/code&gt;) to the function.&lt;/p&gt;

&lt;p&gt;Add the following function declaration in &lt;code&gt;index.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;fabric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;template&lt;/code&gt; will be one object from our template metadata array. Next, we'll get the data needed for the canvas by destructuring the template object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;backgroundUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;textFields&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest of this function will be responsible for setting the canvas' dimensions, setting the background image, and adding the meme's text fields.&lt;/p&gt;

&lt;p&gt;Setting the canvas' dimensions is straightforward with Fabric's &lt;code&gt;canvas.setDimensions&lt;/code&gt; API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;backgroundUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;textFields&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setDimensions&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will ensure that the canvas is the same size as the background image. Next, we'll set the background image with &lt;code&gt;canvas.setBackgroundImage&lt;/code&gt; and give it two arguments: The URL of the  image and a callback to call when the image is loaded. In our case, the template's URL points to an image in the &lt;code&gt;img&lt;/code&gt; directory and the callback will re-render the canvas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setBackgroundImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;backgroundUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renderAll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we need to create the meme's text fields and add them to the canvas. We'll use Fabric's &lt;a href="http://fabricjs.com/docs/fabric.IText.html" rel="noopener noreferrer"&gt;IText&lt;/a&gt; class, which allows us to create interactive text fields that we can reposition, resize, and edit on the canvas directly. The &lt;code&gt;IText&lt;/code&gt; constructor also accepts an options object with options such as the text's font family, size, and color; these options correspond with the properties in the text field objects in our &lt;code&gt;textFields&lt;/code&gt; arrays.&lt;/p&gt;

&lt;p&gt;Our text field objects have the &lt;code&gt;text&lt;/code&gt; property and other style options on one level, but &lt;code&gt;IText&lt;/code&gt;'s constructor expects the text and options to be two different arguments. To fix this, let's map over our template's &lt;code&gt;textFields&lt;/code&gt; to create an array of &lt;code&gt;IText&lt;/code&gt; objects, then add them to the canvas using &lt;code&gt;canvas.add&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iTextFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;textFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;fabric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;IText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;iTextFields&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's verify our implementation of &lt;code&gt;renderTemplate&lt;/code&gt; by importing our meme templates and passing the first value to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;templates&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./meme-templates.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;fabric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;renderTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If all goes well, you should see a nice Doge in your browser:&lt;/p&gt;

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

&lt;p&gt;Try moving around the text fields and editing the text. Fabric gives us this functionality without much effort on our end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the template selectors
&lt;/h2&gt;

&lt;p&gt;Next, let's add the ability to create selector buttons for each of our templates so that our users can edit different memes:&lt;/p&gt;

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

&lt;p&gt;We'll create a function called &lt;code&gt;createSelector&lt;/code&gt; , and it will return a  &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; that will render a template when clicked.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;index.js&lt;/code&gt;, add the &lt;code&gt;createSelector&lt;/code&gt; function declaration that takes a template object as an argument, creates a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; element, and returns it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;templates&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./meme-templates.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;fabric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to identify the template that this button renders, so set the text of the button to be the template's &lt;code&gt;name&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To actually render the template on click, we'll add a click handler that calls &lt;code&gt;renderTemplate&lt;/code&gt; and  adds the &lt;code&gt;.selected-template&lt;/code&gt; class to the current element. Since there will be multiple template selectors, we also need to remove the &lt;code&gt;.selected-template&lt;/code&gt; class from the previously-selected button. Your click handler should look like something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.selected-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;selected-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;selected-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;renderTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! Next, we'll actually create the selectors for all of our templates and render the first template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rendering the template selectors and the initial template
&lt;/h2&gt;

&lt;p&gt;When the generator loads, we want to create template selectors for all of the templates, add them to the DOM, and render the initial template. The selector elements will be added within the aforementioned &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; with the &lt;code&gt;template-selectors&lt;/code&gt; ID; let's start by grabbing that element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;templates&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./meme-templates.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;fabric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Canvas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectorsContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;template-selectors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, for each template, create a selector for it and add it to the selectors container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectorsContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;template-selectors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;templates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;selectorsContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we need to render the first template and add the &lt;code&gt;.selected-template&lt;/code&gt; class to its selector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;selectorsContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;selected-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;renderTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you refresh the page, you should see selectors for all of the templates and the first template rendered in the canvas. Clicking each selector should render its template:&lt;/p&gt;

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

&lt;p&gt;You'll notice that the text fields aren't removed when a new template is selected. To fix this, we need to clear the canvas before a template is rendered. In &lt;code&gt;renderTemplate&lt;/code&gt;, call  &lt;code&gt;canvas.clear&lt;/code&gt; before adding anything to the canvas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;backgroundUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;textFields&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clicking each selector should now render the template as expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a download button
&lt;/h2&gt;

&lt;p&gt;Being able to customize our own meme templates is great, but it'd be nice if we could share them with others. I've added a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; with an ID of &lt;code&gt;download&lt;/code&gt; in the starter code; we'll attach a click handler to it that will create an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; element with the canvas' data and then click it programmatically to download the image to the user's computer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;downloadButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;download&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;downloadButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`meme-generator-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;.png`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code creates a temporary link element and sets its &lt;code&gt;href&lt;/code&gt; property to a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs" rel="noopener noreferrer"&gt;data URL&lt;/a&gt; of the canvas exported as a PNG. We then set the filename of the download and click the link.&lt;/p&gt;

&lt;p&gt;If you customize a template and click the download button, you should see a file with the name &lt;code&gt;meme-generator-&amp;lt;current time&amp;gt;.png&lt;/code&gt; in your downloads folder:&lt;/p&gt;

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

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

&lt;p&gt;Congratulations! You've created your very own meme generator. I hope you enjoyed this tutorial and learned a bit about memes and Fabric.js.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to go from here
&lt;/h3&gt;

&lt;p&gt;The meme generator we've created is fairly simple and could be modified for additional template customization. Below are some ideas to extend this project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add ability to add and remove text fields&lt;/li&gt;
&lt;li&gt;Add ability to change text styles such as font family, color, and outline&lt;/li&gt;
&lt;li&gt;Persist the state of each template in local storage&lt;/li&gt;
&lt;li&gt;Let users upload their own background image&lt;/li&gt;
&lt;li&gt;Add support for template styles that aren't simple text over background image&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're interested in learning more about Fabric.js, I recommend starting with their &lt;a href="http://fabricjs.com/articles/" rel="noopener noreferrer"&gt;Introduction to Fabric.js&lt;/a&gt; tutorials.&lt;/p&gt;




&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this post, connect with me on &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://fabricjs.com/articles/" rel="noopener noreferrer"&gt;Fabric.js | Introduction to Fabric.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API" rel="noopener noreferrer"&gt;MDN | Canvas API&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Original meme image sources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kabosu112.exblog.jp/9944144/" rel="noopener noreferrer"&gt;Atsuko Sato | Doge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jake-clark.tumblr.com/post/100946716432" rel="noopener noreferrer"&gt;Jake Clark | Daily Struggle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.archive.org/web/20091206061155/http://lonelydinosaur.com/apparel/philosoraptor.html" rel="noopener noreferrer"&gt;Sam Smith | Philosoraptor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>html</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Using local NPM packages as dependencies with yalc</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Sat, 14 Aug 2021 23:32:15 +0000</pubDate>
      <link>https://dev.to/zachsnoek/using-local-npm-packages-as-dependencies-with-yalc-2g56</link>
      <guid>https://dev.to/zachsnoek/using-local-npm-packages-as-dependencies-with-yalc-2g56</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you develop NPM packages, you may need to use a local version of a package as a dependency of another. For example, say you have two packages, &lt;code&gt;package-a&lt;/code&gt; and &lt;code&gt;package-b&lt;/code&gt;, where &lt;code&gt;package-a&lt;/code&gt; depends on &lt;code&gt;package-b&lt;/code&gt;. You've made changes to &lt;code&gt;package-b&lt;/code&gt; and want to test them out in &lt;code&gt;package-a&lt;/code&gt; without publishing &lt;code&gt;package-b&lt;/code&gt; to NPM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wclr/yalc" rel="noopener noreferrer"&gt;yalc&lt;/a&gt; solves this problem by allowing you to publish your local dependencies to a local store and make them available for use in dependent projects.&lt;/p&gt;

&lt;p&gt;Immediately below are quick start instructions for easy reference. If you're interested in what &lt;code&gt;yalc&lt;/code&gt; commands do under the hood, continue to How it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;p&gt;Note: &lt;code&gt;package-a&lt;/code&gt; is the local dependent package and &lt;code&gt;package-b&lt;/code&gt; is the local dependency package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Install &lt;code&gt;yalc&lt;/code&gt; globally&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm i -g yalc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; Publish your dependency to the &lt;code&gt;yalc&lt;/code&gt; store&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package-b] $ yalc publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; Add the &lt;code&gt;yalc&lt;/code&gt;-stored dependency to your dependent project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package-a] $ yalc add package-b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3a.&lt;/strong&gt; Install the dependencies of the dependency if they aren't already installed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package-a] $ npm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4.&lt;/strong&gt; After making changes to your dependency, update the package in the store and push the changes to the dependent project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package-b] $ yalc push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5.&lt;/strong&gt; Remove the dependency from the dependent project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[package-a] $ yalc remove package-b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;When using &lt;code&gt;yalc&lt;/code&gt; to add a local package as a dependency, you first &lt;strong&gt;publish&lt;/strong&gt; the dependency to the &lt;code&gt;yalc&lt;/code&gt; store and &lt;strong&gt;add&lt;/strong&gt; it to the dependent project. You can then &lt;strong&gt;update&lt;/strong&gt; the dependency and eventually &lt;strong&gt;remove&lt;/strong&gt; it from the dependent project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Publishing
&lt;/h3&gt;

&lt;p&gt;To add your dependency to the &lt;code&gt;yalc&lt;/code&gt; store, run &lt;code&gt;yalc publish&lt;/code&gt;. This will make a copy of the package in the store, which is located at &lt;code&gt;~/.yalc&lt;/code&gt;. &lt;code&gt;yalc&lt;/code&gt; will also compute the hash signature of the package's files and store it in the store to verify that the correct version of the package is added to other projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;yalc add &amp;lt;dependency&amp;gt;&lt;/code&gt; in your dependent project adds the package published in the store to your project. &lt;code&gt;yalc&lt;/code&gt; will pull the package into the project and place it in &lt;code&gt;.yalc&lt;/code&gt;, and will update the dependency entry in the project's &lt;code&gt;package.json&lt;/code&gt; to point to the local copy.&lt;/p&gt;

&lt;p&gt;For example, running &lt;code&gt;yalc add package-b&lt;/code&gt; in &lt;code&gt;package-a&lt;/code&gt; will create a copy of the dependency at &lt;code&gt;package-a/.yalc/package-b&lt;/code&gt;. &lt;code&gt;package-a&lt;/code&gt;'s &lt;code&gt;package.json&lt;/code&gt; will have a dependency entry for &lt;code&gt;package-b&lt;/code&gt; that points to &lt;code&gt;file:./yalc/package-b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yalc add&lt;/code&gt; will also create a &lt;code&gt;yalc.lock&lt;/code&gt; file in the dependent project that fixes the dependency to the version in the store using the signature created with &lt;code&gt;yalc publish&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;yalc&lt;/code&gt; doesn't install dependencies of the local &lt;code&gt;yalc&lt;/code&gt; package; run &lt;code&gt;npm i&lt;/code&gt; after adding your dependency if it has any dependencies that are not installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating
&lt;/h3&gt;

&lt;p&gt;If you've made changes to your dependency that need to be updated in the dependent project, run &lt;code&gt;yalc push&lt;/code&gt; in the dependency project. This will publish the updated dependency to the store and update the changes in the dependent project.&lt;/p&gt;

&lt;p&gt;Alternatively, you can run &lt;code&gt;yalc publish&lt;/code&gt; in the dependency and then run &lt;code&gt;yalc update&lt;/code&gt; in the dependent project.&lt;/p&gt;

&lt;p&gt;You'll need to run &lt;code&gt;npm i&lt;/code&gt; again in the dependent project if the dependencies of the dependency have changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Removing
&lt;/h3&gt;

&lt;p&gt;Once you have no further use for the local dependency in your project, you can remove it  with &lt;code&gt;yalc remove &amp;lt;dependency&amp;gt;&lt;/code&gt;. This will remove the dependency stored in &lt;code&gt;.yalc&lt;/code&gt; and the &lt;code&gt;yalc&lt;/code&gt; information in &lt;code&gt;yalc.lock&lt;/code&gt; and &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;yalc&lt;/code&gt; makes it easy to use locally-developed packages in other projects. It has some other useful options that I didn't mention here; read more about them on the &lt;a href="https://github.com/wclr/yalc" rel="noopener noreferrer"&gt;project's README&lt;/a&gt;. Hopefully, this helps you get started developing with local packages––good luck!&lt;/p&gt;




&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this post, connect with me on &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/wclr/yalc" rel="noopener noreferrer"&gt;GitHub | wclr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.viget.com/articles/how-to-use-local-unpublished-node-packages-as-project-dependencies/" rel="noopener noreferrer"&gt;Henry Bley-Vroman (Viget) | How to use local Node packages as project dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@mrthetrain?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Joshua Hoehne&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/chain?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>npm</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Making list formatting easy with Intl.ListFormat</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Thu, 22 Jul 2021 01:05:12 +0000</pubDate>
      <link>https://dev.to/zachsnoek/making-list-formatting-easy-with-intl-listformat-276o</link>
      <guid>https://dev.to/zachsnoek/making-list-formatting-easy-with-intl-listformat-276o</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let's say you have an array containing your favorite dog breeds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;favoriteDogs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Corgi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;German Shepherd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Goldendoodle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your goal is to format that list as a string like "Corgi, German Shepherd, and Goldendoodle." One option is to write a basic utility function like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;formatList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; and &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, and &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we'd need to make modifications if we wanted to use &lt;em&gt;or&lt;/em&gt; instead of &lt;em&gt;and&lt;/em&gt;, omit the Oxford comma, or handle different languages. Instead, let's see how we can use &lt;code&gt;Intl.ListFormat&lt;/code&gt; to have JavaScript do this heavy lifting for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intl.ListFormat
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Intl.ListFormat&lt;/code&gt; replaces &lt;code&gt;formatList&lt;/code&gt; with a couple of lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;lf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;favoriteDogs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; Corgi, German Shepherd, and Goldendoodle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Intl.ListFormat&lt;/code&gt; comes from &lt;code&gt;Intl&lt;/code&gt;, which is a built-in object that provides language-sensitive functions. We've provided &lt;code&gt;en&lt;/code&gt; (English) as the &lt;code&gt;locales&lt;/code&gt; argument, which formats the list based on the language or region.&lt;/p&gt;

&lt;p&gt;This gives us a lot of localization power with little effort. For instance, we can specify &lt;code&gt;zh&lt;/code&gt; for traditional Chinese and let it localize the conjunction and punctuation for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;lf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;咖啡&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;茶&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;可樂&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; 咖啡、茶和可樂 (Coffee, tea and coke)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Other formatting options
&lt;/h2&gt;

&lt;p&gt;We can optionally specify a second &lt;code&gt;options&lt;/code&gt; argument that has a &lt;code&gt;style&lt;/code&gt; and &lt;code&gt;type&lt;/code&gt; property. &lt;code&gt;style&lt;/code&gt; is the length of the output and can be &lt;code&gt;long&lt;/code&gt; (the default), &lt;code&gt;short&lt;/code&gt; or &lt;code&gt;narrow&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;favoriteDogs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; Corgi, German Shepherd, &amp;amp; Goldendoodle&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;narrow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;favoriteDogs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; Corgi, German Shepherd, Goldendoodle&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;type&lt;/code&gt; describes the list type, which is &lt;code&gt;conjunction&lt;/code&gt; (&lt;em&gt;and&lt;/em&gt;-based) by default. It can be used to make our list &lt;code&gt;disjunctive&lt;/code&gt; or suitable for units:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;disjunction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;favoriteDogs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; Corgi, German Shepherd, or Goldendoodle&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;6 feet&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2 inches&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;gt; 6 feet, 2 inches&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Instead of writing a list formatting function, consider using &lt;code&gt;Intl.ListFormat&lt;/code&gt;. There are a lot of other useful functions from &lt;code&gt;Intl&lt;/code&gt;, too; check them out at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kentcdodds.com/blog/listify-a-java-script-array" rel="noopener noreferrer"&gt;KCD | Listify a JavaScript Array&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl" rel="noopener noreferrer"&gt;MDN | Intl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat" rel="noopener noreferrer"&gt;MDN | Intl.ListFormat() constructor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this post, connect with me on &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Converting values to boolean using !! (double NOT)</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Thu, 01 Jul 2021 02:23:21 +0000</pubDate>
      <link>https://dev.to/zachsnoek/converting-values-to-boolean-using-double-not-18h4</link>
      <guid>https://dev.to/zachsnoek/converting-values-to-boolean-using-double-not-18h4</guid>
      <description>&lt;p&gt;Something I come across working in JavaScript and React projects is the use of two logical NOT operators to coerce a value to its corresponding boolean value. This might look strange or confusing at first, so let's see how it works and why you may (or may not) use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The logical NOT operator (&lt;code&gt;!&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;In JavaScript, all values are either &lt;a href="https://dev.to/zachsnoek/what-are-truthy-and-falsy-in-javascript-j68"&gt;truthy or falsy&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JavaScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// truthy&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// falsy&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;            &lt;span class="c1"&gt;// truthy&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;             &lt;span class="c1"&gt;// falsy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the logical NOT operator (&lt;code&gt;!&lt;/code&gt;), we can convert a truthy value to &lt;code&gt;false&lt;/code&gt; and a falsy value to &lt;code&gt;true&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JavaScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;            &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;             &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;!&lt;/code&gt; always returns a boolean value: It first converts the truthy or falsy value to its corresponding boolean value (truthy corresponds to &lt;code&gt;true&lt;/code&gt; and falsy to &lt;code&gt;false&lt;/code&gt;), then returns the negated boolean. For example, &lt;code&gt;!{}&lt;/code&gt; first converts &lt;code&gt;{}&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; and then returns the opposite of &lt;code&gt;true&lt;/code&gt;, which is &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The double NOT (&lt;code&gt;!!&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;You might come across a situation where you want to use a non-boolean value as a boolean. A double NOT (&lt;code&gt;!!&lt;/code&gt;) allows us to succinctly convert a non-boolean value to its corresponding boolean value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JavaScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With our knowledge of how the logical NOT operator works, we can see how this makes sense. Take &lt;code&gt;!!"JavaScript"&lt;/code&gt;, for instance:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;"JavaScript"&lt;/code&gt; is truthy, so it is converted to &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The first &lt;code&gt;!&lt;/code&gt; converts &lt;code&gt;true&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The second &lt;code&gt;!&lt;/code&gt; converts &lt;code&gt;false&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that &lt;code&gt;!!&lt;/code&gt; is not an operator––it's just two logical NOT operators chained together. In fact, we can use as many &lt;code&gt;!&lt;/code&gt;s as we like (and make our JavaScript look like it's gone into expletive mode):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!!!!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s***&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using &lt;code&gt;!!&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I don't often use &lt;code&gt;!!&lt;/code&gt;, but I think there are a few instances where it can be useful. Consider a function that performs logic on non-boolean values that we want to ensure returns a boolean value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isValidUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;bio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bio&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also use &lt;code&gt;!!&lt;/code&gt; as a shortcut for checking if a list has any elements; this is something I often see in React:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;FruitDisplay&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fruit&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasFruit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;fruit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;hasFruit&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Available fruit:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fruit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fruit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;orange&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grape&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FruitDisplay&lt;/span&gt; &lt;span class="na"&gt;fruit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fruit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;//...&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, it's &lt;a href="https://stackoverflow.com/a/1406618" rel="noopener noreferrer"&gt;often argued&lt;/a&gt; that &lt;code&gt;!!&lt;/code&gt; decreases readability and is used in situations that could be refactored to be more explicit. In our previous list length example, I'd argue that checking for &lt;code&gt;&amp;gt; 0&lt;/code&gt; or &lt;code&gt;!== 0&lt;/code&gt; is more clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;FruitDisplay&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fruit&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasFruit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fruit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// or fruit.length !== 0&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it's worth noting that using the built-in &lt;code&gt;Boolean&lt;/code&gt; function does the same thing as &lt;code&gt;!!&lt;/code&gt; and is arguably more readable and easier to understand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                      &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JavaScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JavaScript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The double NOT allows us to convert truthy and falsy values to their corresponding boolean value: truthy values become &lt;code&gt;true&lt;/code&gt; and falsy values become &lt;code&gt;false&lt;/code&gt;. It's a concise way to coerce any value to a boolean but can also sacrifice readability.&lt;/p&gt;

&lt;p&gt;Do you like to use &lt;code&gt;!!&lt;/code&gt;? What situations do you find it useful or harmful? Let me know your thoughts below!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean" rel="noopener noreferrer"&gt;MDN | Boolean&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_NOT" rel="noopener noreferrer"&gt;MDN | Logical NOT (!)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://medium.com/@edplatomail/js-double-bang-or-the-not-operator-part-40e55d089bf0" rel="noopener noreferrer"&gt;Edward Plato | JS Double Bang –– or "The Not Operator Part !!"&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you liked this post, come connect with me on &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Understanding JavaScript Prototypes</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Tue, 18 May 2021 03:40:02 +0000</pubDate>
      <link>https://dev.to/zachsnoek/understanding-javascript-prototypes-50c5</link>
      <guid>https://dev.to/zachsnoek/understanding-javascript-prototypes-50c5</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When you first learned JavaScript, you might have started by writing something simple like creating a string primitive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You likely even learned how to use &lt;code&gt;split&lt;/code&gt; to turn that string into an array of substrings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// output: ["Hello", " world!"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You didn't implement &lt;code&gt;split&lt;/code&gt; yourself, though. Instead, &lt;code&gt;split&lt;/code&gt; is defined on &lt;code&gt;hello&lt;/code&gt;'s prototype object, which comes from &lt;code&gt;String&lt;/code&gt;. Prototypes are JavaScript's method of inheritance and it allows properties to be shared across all object instances.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prototypes
&lt;/h2&gt;

&lt;p&gt;All JavaScript objects have a prototype, which is an object that it inherits properties from. This prototype object is a property on the constructor function that the inheriting object was created from, and the inheriting object links to it.&lt;/p&gt;

&lt;p&gt;An object's prototype can have its own prototype, and that prototype can have its own prototype; this prototype chain continues until a prototype points to &lt;code&gt;null&lt;/code&gt;, which is the end of the chain. Most objects are instances of &lt;code&gt;Object&lt;/code&gt;, so the prototype chain will eventually link back to &lt;code&gt;Object&lt;/code&gt;'s prototype property, which is &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This diagram, modified from &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes" rel="noopener noreferrer"&gt;MDN&lt;/a&gt; and created with &lt;a href="https://www.excalidraw.com" rel="noopener noreferrer"&gt;Excalidraw&lt;/a&gt;, shows one way you can think about the prototypal inheritance of &lt;code&gt;hello&lt;/code&gt;:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The &lt;code&gt;prototype&lt;/code&gt; property and an object's prototype
&lt;/h2&gt;

&lt;p&gt;A constructor function defines the prototype object on its &lt;code&gt;prototype&lt;/code&gt; property; this is the object that all inheriting objects will link to. For example, to see all of the properties inherited by instances of &lt;code&gt;String&lt;/code&gt;, we can log &lt;code&gt;String.prototype&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    anchor: ƒ anchor()
    big: ƒ big(),
    ...
    split: ƒ split()
    ...
    __proto__: Object
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To access the prototype of an object, we can call &lt;code&gt;Object.getPrototypeOf(obj)&lt;/code&gt; or use the &lt;code&gt;__proto__&lt;/code&gt; property of the object in many web browsers. Since &lt;code&gt;hello&lt;/code&gt; is an instance of &lt;code&gt;String&lt;/code&gt; (or, coerced to &lt;code&gt;String&lt;/code&gt; at runtime), we should expect to see it linked to the prototype object defined by the &lt;code&gt;String&lt;/code&gt; constructor function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    anchor: ƒ anchor()
    big: ƒ big(),
    ...
    split: ƒ split()
    ...
    __proto__: Object
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The prototype chain
&lt;/h2&gt;

&lt;p&gt;We've discussed what prototypes are and how instances link to them, but how does this allow objects to inherit properties? To find the property of an object, JavaScript will "walk up" the prototype chain. First, it will look at the calling object's properties. If the property is not found there, it will look at its prototype's properties. This continues until the property is found or the end of the prototype chain is reached.&lt;/p&gt;

&lt;p&gt;An instance of &lt;code&gt;String&lt;/code&gt; is an object that inherits from &lt;code&gt;Object&lt;/code&gt;, so &lt;code&gt;String&lt;/code&gt;'s prototype is the prototype defined on &lt;code&gt;Object&lt;/code&gt;'s constructor function. Because of this, we can access the properties defined on &lt;code&gt;Object&lt;/code&gt;'s prototype such as &lt;code&gt;toLocaleString&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// output: "Hello, world!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we called &lt;code&gt;hello.toLocaleString()&lt;/code&gt;, JavaScript:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checked for the property on &lt;code&gt;hello&lt;/code&gt; and did not find it&lt;/li&gt;
&lt;li&gt;Checked &lt;code&gt;hello&lt;/code&gt;'s prototype, the prototype object defined by &lt;code&gt;String&lt;/code&gt;, and did not find it&lt;/li&gt;
&lt;li&gt;Checked &lt;code&gt;String&lt;/code&gt;'s prototype, the prototype object defined by &lt;code&gt;Object&lt;/code&gt;, and did find it&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: MDN is a handy way to tell which properties are defined on the prototype of built-in objects. For instance, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array" rel="noopener noreferrer"&gt;Array&lt;/a&gt; page links to documentation for all of the different properties, such as &lt;code&gt;map&lt;/code&gt; and &lt;code&gt;pop&lt;/code&gt;, that are defined on &lt;code&gt;Array.prototype&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Walking the prototype chain in JavaScript
&lt;/h3&gt;

&lt;p&gt;We briefly saw a simple graphical representation of &lt;code&gt;hello&lt;/code&gt;'s prototype chain earlier. Now that we know how to access an object's prototype, we can write our own function to show the chain programmatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;walkPrototypeChain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Inherits from:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Reached of prototype chain:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: &lt;code&gt;current.constructor.name&lt;/code&gt; is the name of the constructor function that defines the prototype.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If we run this in the browser with &lt;code&gt;hello&lt;/code&gt;, we get the following output:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Extending a prototype
&lt;/h2&gt;

&lt;p&gt;We can easily define our own properties on a constructor function's &lt;code&gt;prototype&lt;/code&gt; property. Let's say we have a program that creates many arrays that we commonly want to ensure only contain truthy values. We can define a &lt;code&gt;whereNotFalsy&lt;/code&gt; property on &lt;code&gt;Array&lt;/code&gt;'s prototype to make this available on every array we create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;whereNotFalsy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can call &lt;code&gt;whereNotFalsy&lt;/code&gt; on the subsequent arrays we create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasFalsyValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasFalsyValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;whereNotFalsy&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// output: ["Hello, world!"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Prototypes allow objects to inherit shared properties. An object's prototype refers to the object that it inherits properties from. This prototype object is defined on the &lt;code&gt;prototype&lt;/code&gt; property of the constructor function that&lt;br&gt;
creates it. Inheriting objects contain a link to the prototype object and it can be accessed through the &lt;code&gt;__proto__&lt;/code&gt; property in web browsers or by calling &lt;code&gt;Object.getPrototypeOf&lt;/code&gt; in other contexts.&lt;/p&gt;

&lt;p&gt;When an object's property is accessed, JavaScript first checks its own properties, then walks its prototype chain to find the property––this is how objects are able to inherit properties through prototypes. Lastly, we can directly modify the prototype of a constructor function by accessing its &lt;code&gt;prototype&lt;/code&gt; property, which will affect all inheriting objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes" rel="noopener noreferrer"&gt;MDN | Object prototypes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain" rel="noopener noreferrer"&gt;MDN | Inheritance and the prototype chain&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@d_mccullough?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Daniel McCullough&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you liked this post, come connect with me on &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>An introduction to constructor functions</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Mon, 19 Apr 2021 15:05:36 +0000</pubDate>
      <link>https://dev.to/zachsnoek/an-introduction-to-constructor-functions-3bik</link>
      <guid>https://dev.to/zachsnoek/an-introduction-to-constructor-functions-3bik</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;If you're new to JavaScript and have experience in a class-based object-oriented language, you might be wondering how you can create custom objects in JavaScript. In this post, you'll learn about constructor functions, which is one method of creating user-defined objects and function similarly to classes.&lt;/p&gt;

&lt;p&gt;To fully understand this post, you should be familiar with JavaScript and have a basic understanding of JavaScript functions and objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;Car&lt;/code&gt; object
&lt;/h2&gt;

&lt;p&gt;We'll be creating a constructor function to create &lt;code&gt;Car&lt;/code&gt; objects. Here's how an object representing a 1999 Honda Accord might look like if we defined it using object literal syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Honda&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Accord&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;bodyStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sedan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1999&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`This &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accord&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accord&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accord&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bodyStyle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was built in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accord&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.`&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Output: "This Honda Accord sedan was built in 1999."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we just have some one-off car object that we need to make, this would be fine. But if you need to represent a lot of different cars, it would be nice to have a way to reuse common &lt;code&gt;Car&lt;/code&gt; properties. This is where constructor functions come in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a constructor function
&lt;/h2&gt;

&lt;p&gt;A constructor function is a function that creates a new object. Creating it is similar to creating any other function in JavaScript: it can have parameters, has a name, and is declared with the &lt;code&gt;function&lt;/code&gt; keyword. We'll create a &lt;code&gt;Car&lt;/code&gt; constructor function that takes in the &lt;code&gt;make&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;bodyStyle&lt;/code&gt;, and &lt;code&gt;year&lt;/code&gt; as arguments; here is what it looks like without its body implemented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bodyStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO: Set properties&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: By convention, constructor functions start with a capital letter (Pascal case) so that we properly initialize them and don't confuse them with non-constructor functions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can set the properties of our custom object by defining them on &lt;code&gt;this&lt;/code&gt;, which will refer to the new object that is created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bodyStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;make&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bodyStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bodyStyle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This almost looks like typical class syntax from an object-oriented language, but it's a function––and we're not returning anything. So what's happening here? To understand this, let's look at how we create an instance of our &lt;code&gt;Car&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an instance of Car with &lt;code&gt;new&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Creating an instance of &lt;code&gt;Car&lt;/code&gt; is like calling a normal JavaScript function, but we also use the &lt;code&gt;new&lt;/code&gt; keyword before the function name. You may be familiar with this syntax if you've used a class-based language such as Java or C#. Here's how we create an instance of the same &lt;code&gt;accord&lt;/code&gt; defined earlier but with our new constructor function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Honda&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Accord&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sedan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1999&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we know how to create a &lt;code&gt;Car&lt;/code&gt; object, let's clarify how this is working. When we call a constructor function with &lt;code&gt;new&lt;/code&gt;, JavaScript will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create a new, empty object&lt;/li&gt;
&lt;li&gt;  Call the constructor function with the value of &lt;code&gt;this&lt;/code&gt; pointing to the new object

&lt;ul&gt;
&lt;li&gt;  Thus, the properties specified on &lt;code&gt;this&lt;/code&gt; in the function will be set on the new object&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  Return the new object&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Under the hood, this process looks similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create a new object&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="c1"&gt;// Call Car, with the value of `this` being the new `obj` object&lt;/span&gt;
&lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Honda&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Accord&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sedan&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1999&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Return obj&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding a method
&lt;/h2&gt;

&lt;p&gt;Just having a property for the car's model year probably isn't that interesting. Let's create a method that will return a car's age. To do this, we'll add a &lt;code&gt;getAge&lt;/code&gt; property on &lt;code&gt;Car&lt;/code&gt;'s prototype property. It will be a function that returns the age as a number:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getFullYear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simply put, properties on an constructor function's prototype property are inherited by every instance. But why can't we just define &lt;code&gt;getAge&lt;/code&gt; as a property of &lt;code&gt;Car&lt;/code&gt;? Here's what that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bodyStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;make&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bodyStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bodyStyle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getFullYear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is valid and will give you the same behavior. However, this creates a &lt;code&gt;getAge&lt;/code&gt; function every time a new &lt;code&gt;Car&lt;/code&gt; is created. By placing the property onto &lt;code&gt;Car&lt;/code&gt;'s prototype, we can share one reference to the function across all instances. (This is not very useful in our example, but is important to be aware of.)&lt;/p&gt;

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

&lt;p&gt;Constructor functions in JavaScript allow us to create custom objects. They are declared like other functions, but set properties on &lt;code&gt;this&lt;/code&gt; and are instantiated with the &lt;code&gt;new&lt;/code&gt; keyword. We capitalize the function name so that we know it's a constructor function.&lt;/p&gt;

&lt;p&gt;Now that you've learned about constructor functions, you might be interested in learning about how inheritance and prototypes work. I will be writing a blog post on this soon and will update this post once it is published. In the meantime, you can read &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain" rel="noopener noreferrer"&gt;Inheritance and the prototype chain&lt;/a&gt; from MDN.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@carlosaranda?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;carlos aranda&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/assembly-line?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript" rel="noopener noreferrer"&gt;MDN | A re-introduction to JavaScript&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply" rel="noopener noreferrer"&gt;MDN| Function.prototype.apply()&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new#description" rel="noopener noreferrer"&gt;MDN | new operator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes" rel="noopener noreferrer"&gt;MDN | Object prototypes&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you liked this post, come connect with me on &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Creating Custom React Hooks: useConfirmTabClose</title>
      <dc:creator>Zach Snoek</dc:creator>
      <pubDate>Tue, 30 Mar 2021 05:31:54 +0000</pubDate>
      <link>https://dev.to/zachsnoek/creating-custom-react-hooks-useconfirmtabclose-eno</link>
      <guid>https://dev.to/zachsnoek/creating-custom-react-hooks-useconfirmtabclose-eno</guid>
      <description>&lt;p&gt;It's common to come across a situation where a user can navigate away from unsaved changes. For example, a social media site could have a user profile information form. When a user submits the form their data are saved, but if they close the tab before saving, their data are lost. Instead of losing the user's data, it would be nice to show the user a confirmation dialog that warns them of losing unsaved changes when they try to close the tab.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example use case
&lt;/h2&gt;

&lt;p&gt;To demonstrate, we'll use a simple form that contains an input for the user's name and a button to "save" their name. (In our case, clicking "save" doesn't do anything useful; this is a &lt;em&gt;contrived&lt;/em&gt; example.) Here's what that component looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NameForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setHasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Your name:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
                    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;
                    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;
                    &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setHasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    Save changes
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    You have&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;
                        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt;
                                &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebrick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forestgreen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;not saved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;saved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    your changes.
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is the form in use:&lt;/p&gt;

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

&lt;p&gt;If the user closes the tab without saving their name first, we want to show a confirmation dialog that looks similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhh73zx5d5hidrw96yo4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhh73zx5d5hidrw96yo4.png" alt="Screen Shot 2021-03-29 at 7.57.17 PM" width="278" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom hook solution
&lt;/h2&gt;

&lt;p&gt;We'll create a hook named &lt;code&gt;useConfirmTabClose&lt;/code&gt; that will show the dialog if the user tries to close the tab when &lt;code&gt;hasUnsavedChanges&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;. We can use it in our component like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NameForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;useConfirmTabClose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can read this hook as "confirm the user wants to close the tab if they have unsaved changes."&lt;/p&gt;

&lt;h2&gt;
  
  
  Showing the confirmation dialog
&lt;/h2&gt;

&lt;p&gt;To implement this hook, we need to know when the user has closed the tab and show the dialog. We can add an event listener for the &lt;code&gt;beforeunload&lt;/code&gt; event to detect when the window, the document, and the document's resources are about to be unloaded (see References for more information about this event).&lt;/p&gt;

&lt;p&gt;The event handler that we provide can tell the browser to show the confirmation dialog. The way this is implemented varies by browser, but I've found success on Chrome and Safari by assigning a non-empty string to &lt;code&gt;event.returnValue&lt;/code&gt; and also by returning a string. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You have unsaved changes. Continue?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleBeforeUnload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;returnValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;beforeunload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleBeforeUnload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: The string returned or assigned to &lt;code&gt;event.returnValue&lt;/code&gt; may not be shown in the confirmation dialog as that feature is deprecated and not widely supported. Also, the way that we indicate that the dialog should be opened is not consistently implemented across browsers. According to MDN, the spec states that the event handler should call &lt;code&gt;event.preventDefault()&lt;/code&gt; to show the dialog, though Chrome and Safari don't seem to respect this.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hook implementation
&lt;/h2&gt;

&lt;p&gt;Now that we know how to show the confirmation dialog, let's start creating the hook. We'll take one argument, &lt;code&gt;isUnsafeTabClose&lt;/code&gt;, which is some boolean value that should tell us if we should show the confirmation dialog. We'll also add the &lt;code&gt;beforeunload&lt;/code&gt; event listener in an &lt;code&gt;useEffect&lt;/code&gt; hook and ensure that we remove the event listener once the component has unmounted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You have unsaved changes. Continue?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useConfirmTabClose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isUnsafeTabClose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleBeforeUnload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;beforeunload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleBeforeUnload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;beforeunload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleBeforeUnload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isUnsafeTabClose&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We know that we can assign &lt;code&gt;event.returnValue&lt;/code&gt; or return a string from the &lt;code&gt;beforeunload&lt;/code&gt; handler to show the confirmation dialog, so in &lt;code&gt;handleBeforeUnload&lt;/code&gt; we can simply do that if &lt;code&gt;isUnsafeTabClose&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You have unsaved changes. Continue?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useConfirmTabClose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isUnsafeTabClose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleBeforeUnload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isUnsafeTabClose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;returnValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Putting those together, we have the final version of our hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You have unsaved changes. Continue?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useConfirmTabClose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isUnsafeTabClose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleBeforeUnload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isUnsafeTabClose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;returnValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;confirmationMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;beforeunload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleBeforeUnload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;beforeunload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleBeforeUnload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isUnsafeTabClose&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final component
&lt;/h2&gt;

&lt;p&gt;Here is the final version of &lt;code&gt;NameForm&lt;/code&gt; after adding our custom hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NameForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;useConfirmTabClose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;setHasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Your name:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
                    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;
                    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;
                    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;
                    &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setHasUnsavedChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    Save changes
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    You have&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;
                        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt;
                                &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebrick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                                &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forestgreen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hasUnsavedChanges&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;not saved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;saved&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    your changes.
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this post, we used the &lt;code&gt;beforeunload&lt;/code&gt; event to alert the user when closing a tab with unsaved changes. We created &lt;code&gt;useConfirmTabClose&lt;/code&gt;, a custom hook that adds and removes the &lt;code&gt;beforeunload&lt;/code&gt; event handler and checks if we should show a confirmation dialog or not.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/BeforeUnloadEvent#examples" rel="noopener noreferrer"&gt;MDN | BeforeUnloadEvent&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event" rel="noopener noreferrer"&gt;MDN | Window: beforeunload event&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload" rel="noopener noreferrer"&gt;MDN | WindowEventHandlers.onbeforeunload&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover photo by &lt;a href="https://unsplash.com/@whaleitsjessica?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Jessica Tan&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/caution?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Let's connect
&lt;/h2&gt;

&lt;p&gt;If you liked this post, come connect with me on &lt;a href="https://twitter.com/zach_snoek" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/zach-snoek-5b327b179/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, and &lt;a href="https://github.com/zachsnoek" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;! You can also &lt;a href="https://mailchi.mp/2df4b6d5458f/signup-page" rel="noopener noreferrer"&gt;subscribe to my mailing list&lt;/a&gt; and get the latest content and news from me.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
