<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Non-Traditional Dev: Unconventional Web Development Insights]]></title><description><![CDATA[Unleash your creativity with Non-Traditional Dev's unique web dev content. Stay up-to-date on trends, tips, and tricks for building stunning websites.]]></description><link>https://non-traditional.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1638999422358/CLDVOiWyE.png</url><title>Non-Traditional Dev: Unconventional Web Development Insights</title><link>https://non-traditional.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 21:27:32 GMT</lastBuildDate><atom:link href="https://non-traditional.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How Breaking Bedrock Simplifies Layout Design]]></title><description><![CDATA[There’s a moment in every design system’s life when the small compromises add up—one more alias, one more “temporary” prop, one more legacy fallback. Over time, those conveniences stop being conveniences. They become friction.
This release is about c...]]></description><link>https://non-traditional.dev/how-breaking-bedrock-simplifies-layout-design</link><guid isPermaLink="true">https://non-traditional.dev/how-breaking-bedrock-simplifies-layout-design</guid><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Tue, 03 Feb 2026 18:25:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/8pZKxegqnU4/upload/5aea4ad778a7d77ea2a63f8e2b33d521.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There’s a moment in every design system’s life when the small compromises add up—one more alias, one more “temporary” prop, one more legacy fallback. Over time, those conveniences stop being conveniences. They become friction.</p>
<p>This release is about clearing that friction out. It’s a tightening pass on Bedrock Layout: fewer legacy props, clearer semantics, and a stronger alignment with native CSS.</p>
<h2 id="heading-the-shape-of-the-change"><strong>The shape of the change</strong></h2>
<p>We’re not trying to be clever here. The breaking changes are intentionally boring—in the best way. They make the system easier to reason about and easier to teach.</p>
<h3 id="heading-gap-means-gap"><strong>Gap means gap</strong></h3>
<p>The old <code>gutter</code> prop is gone. We now use <code>gap</code> everywhere. That’s the vocabulary CSS already gives us, and it’s the one everyone already understands.</p>
<p><strong>Migration:</strong></p>
<ul>
<li>Replace <code>gutter</code> with <code>gap</code> anywhere you’re using layout primitives.</li>
</ul>
<h3 id="heading-columns-now-say-what-they-mean"><strong>Columns now say what they mean</strong></h3>
<p><code>columns</code> was ambiguous. <code>colCount</code> isn’t. It reads like a config value, not a layout command. That clarity matters.</p>
<p><strong>Migration:</strong></p>
<ul>
<li>Replace <code>columns={...}</code> with <code>colCount={...}</code>.</li>
</ul>
<h3 id="heading-custom-spacing-without-a-theme-provider"><strong>Custom spacing without a theme provider</strong></h3>
<p>The docs now emphasize the simplest, most portable path: if you want to plug in your own spacing tokens, use CSS custom properties directly.</p>
<p><strong>Example:</strong></p>
<pre><code>&lt;Stack gap=<span class="hljs-string">"var(--space-3)"</span>&gt;{...}&lt;/Stack&gt;
</code></pre><p>No magic. No wrapper. Just your tokens.</p>
<h3 id="heading-column-offsets-now-match-the-css-api"><strong>Column offsets now match the CSS API</strong></h3>
<p>We aligned offset variables to the CSS-side naming (<code>--offset-start</code> / <code>--offset-end</code>). It’s a consistency fix—no behavioral change—but it eliminates a mismatch that was easy to trip over.</p>
<h3 id="heading-components-removed-to-reduce-surface-area"><strong>Components removed to reduce surface area</strong></h3>
<p>Some components have been removed rather than kept as thin wrappers. The goal is to keep the core primitives focused and avoid maintaining redundant APIs. This means AppBoundary and PadBox Components are gone. MasonryGrid has also been removed, as the new native Masonry layout spec is being developed.</p>
<p><strong>Migration:</strong></p>
<ul>
<li>Replace removed components with the recommended primitives (e.g., layout primitives plus <code>style</code> or small wrapper components).</li>
</ul>
<h3 id="heading-utility-hooks-moved-to-a-separate-repo"><strong>Utility hooks moved to a separate repo</strong></h3>
<p>Legacy utility hooks have been migrated from this repo to a dedicated package. They’re still available, just no longer part of the core Bedrock Layout surface.</p>
<p><strong>Migration:</strong></p>
<ul>
<li>Install and import the hooks from the new utilities package rather than from the main Bedrock Layout repo.</li>
</ul>
<h2 id="heading-why-were-doing-this"><strong>Why we’re doing this</strong></h2>
<p>The core goal is to make Bedrock Layout boringly predictable. That means:</p>
<ul>
<li><p>fewer aliases,</p>
</li>
<li><p>fewer “legacy” escape hatches,</p>
</li>
<li><p>and fewer places where the docs disagree with the code.</p>
</li>
</ul>
<p>If you’re upgrading, the migration is straightforward and mechanical. But the payoff is bigger than a clean diff: it’s a layout system that’s easier to explain, easier to onboard to, and easier to keep stable long-term.</p>
]]></content:encoded></item><item><title><![CDATA[Resizing Elements with Confidence: How to Fix ResizeObserver API]]></title><description><![CDATA[The ResizeObserver API is a relatively new feature in JavaScript that allows developers to detect changes in the size of an element on a web page. This can be incredibly useful for creating responsive designs and optimizing the performance of your we...]]></description><link>https://non-traditional.dev/resizing-elements-with-confidence-how-to-fix-resizeobserver-api</link><guid isPermaLink="true">https://non-traditional.dev/resizing-elements-with-confidence-how-to-fix-resizeobserver-api</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[React]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Thu, 16 Feb 2023 20:56:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/fr3YLb9UHSQ/upload/v1669821044163/1Nb9gGLCN.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The ResizeObserver API is a relatively new feature in JavaScript that allows developers to detect changes in the size of an element on a web page. This can be incredibly useful for creating responsive designs and optimizing the performance of your website. However, the API may not be intuitive oh how best to use it in modern frameworks like React.</p>
<p>In this post, we'll take a closer look at the ResizeObserver API and how it can be improved to make it easier to use in your projects.</p>
<h2 id="heading-the-resizeobserver-api">The ResizeObserver API</h2>
<p>The ResizeObserver API provides a way to observe changes in the size of a DOM element. It creates a new ResizeObserver object, which can then be used to observe a specific element. The observer will be notified whenever the size of the observed element changes and can take appropriate action in response.</p>
<p>To use the ResizeObserver API, you'll first need to create a new ResizeObserver object. You can do this by calling the ResizeObserver constructor, passing in a callback function that will be called whenever the size of an observed element changes.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> observer = <span class="hljs-keyword">new</span> ResizeObserver(<span class="hljs-function"><span class="hljs-params">entries</span> =&gt;</span> {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> entry <span class="hljs-keyword">of</span> entries) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Element: <span class="hljs-subst">${entry.target}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Width: <span class="hljs-subst">${entry.contentRect.width}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Height: <span class="hljs-subst">${entry.contentRect.height}</span>`</span>);
  }
});
</code></pre>
<p>Once you have created your observer, you can use the <code>observe()</code> method to start observing a specific element. This method takes a single argument, which is the element you want to observe.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myElement = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.my-element'</span>);
observer.observe(myElement);
</code></pre>
<p>It's also possible to observe multiple elements at once by calling the <code>observe()</code> method.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> elements = <span class="hljs-built_in">document</span>.querySelectorAll(<span class="hljs-string">'.my-element'</span>);
observer.observe(elements);
</code></pre>
<p>The ResizeObserver API also provides a way to stop observing an element using the <code>unobserve()</code> method. This method takes a single argument, which is the element that you no longer want to observe.</p>
<pre><code class="lang-javascript">observer.unobserve(myElement);
</code></pre>
<p>You can also stop observing all elements by calling the disconnect() method on the observer.</p>
<pre><code class="lang-javascript">observer.disconnect();
</code></pre>
<h2 id="heading-whats-the-problem-then">What's the Problem, then?</h2>
<p>The ResizeObserver API provides a powerful and efficient way to detect changes in the size of an element on a web page. Still, it is designed to be a one Observer fits all scenario. The callback we provide will be given all the observed elements resizing, and then, depending on the element, you can make various choices.</p>
<p>In practice, you are either creating too many resize observers because you want to run a unique callback for each element, like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> mainObserver = <span class="hljs-keyword">new</span> ResizeObserver(<span class="hljs-function">()=&gt;</span>{})
mainObserver.observe(mainElement)

<span class="hljs-keyword">const</span> sideBarObserver = <span class="hljs-keyword">new</span> ResizeObserver(<span class="hljs-function">()=&gt;</span>{})
sideBarObserver.observe(asideElement)

<span class="hljs-comment">// ect.</span>
</code></pre>
<p>Or you stuff a whole bunch of logic into this huge monolithic observer function like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> monolithicObserver = <span class="hljs-keyword">new</span> Resize Observer(<span class="hljs-function"><span class="hljs-params">entries</span>=&gt;</span>{
    <span class="hljs-keyword">const</span> entries.forEach(<span class="hljs-function"><span class="hljs-params">entry</span>=&gt;</span>{
        <span class="hljs-comment">/**
        * check each entry and run a unique set of code for 
        * Matching entries
        */</span>
    })
})
</code></pre>
<p>Neither option is ideal. So I created an abstraction that lets me have the best of both worlds. It's called <code>@bedrock-layout/register-resize-callback</code>, and it's part of my Bedrock Layout Primitives library, found over at bedrock-layout.dev.</p>
<p>What is unique about this package is that it lets me register a special callback for each element I want to observe without having to instantiate multiple Resize Observers. In a future blog post, we can go into how it works, but for now, let's look at how you use it:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { init, registerCallback } <span class="hljs-keyword">from</span> <span class="hljs-string">'@bedrock-layout/register-resize-callback'</span>;

<span class="hljs-comment">// initialize in a safe way when you know you are in the browser</span>
init()

<span class="hljs-keyword">const</span> header = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'header'</span>);
<span class="hljs-keyword">const</span> article = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'article'</span>);

<span class="hljs-comment">// register a callback for each node</span>
<span class="hljs-comment">// This will return a cleanup function</span>
<span class="hljs-keyword">const</span> cleanupHeader = registerCallback(header, <span class="hljs-function">(<span class="hljs-params">entry</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(entry);
})

<span class="hljs-keyword">const</span> cleanupArticle = registerCallback(article, <span class="hljs-function">(<span class="hljs-params">entry</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(entry);
})

<span class="hljs-comment">//unregister the callback</span>
cleanupHeader()
cleanupArticle()
</code></pre>
<p>In the above code, we call the <code>init</code> function as soon as possible to initialize the <code>ResizeObserver</code> that our register callback depends on. This gives you the control you need to ensure that the initialization only happens in the browser. The init function only needs to be called once, but it can be called multiple times without consequences.</p>
<p>Once we are confident that everything is initialized properly. Then we use the <code>registerCallback</code> function to register a callback for each node we want to observe. If that element is resized, our callback will be called with the associated entry for that element. This allows your callback to focus on just that element you want to observe without worrying about anything else.</p>
<p>Finally, when we no longer want to observe those elements anymore, we can call the cleanup function that is returned from `<code>registerCallback` </code> which will both unregister our function and unobserve the element if no other callbacks have been registered on that same element.</p>
<p>Let's say you wanted to observe an element in a React application. Your component might look something like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, {useRef, useEffect} <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { init, registerCallback } <span class="hljs-keyword">from</span> <span class="hljs-string">'@bedrock-layout/register-resize-callback'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params"></span>)</span>{
  <span class="hljs-keyword">const</span> ref = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> currentDiv = ref.current
  useEffect(<span class="hljs-function">() =&gt;</span> {
    init();
    <span class="hljs-keyword">if</span>(currentDiv){
     <span class="hljs-keyword">return</span> registerCallback(currentDiv, <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">// do stuff</span>
      })
    }
  },[currentDiv]);

  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{ref}</span>&gt;</span>{/* stuff goes here*/}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<p>The ResizeObserver is powerful and allows you to do fantastic and dynamic things. Using the <code>@bedrock-layout/register-resize-callback</code> package makes it even more intuitive and practical in your apps.</p>
]]></content:encoded></item><item><title><![CDATA[Breaking Bedrock]]></title><description><![CDATA[A few years ago, I started what ended up becoming the Bedrock Layout Primitive library. What began as a bit of a "revenge" driven project ended up becoming a passion. It resulted in an opportunity to create a course on composing layouts in react and ...]]></description><link>https://non-traditional.dev/breaking-bedrock</link><guid isPermaLink="true">https://non-traditional.dev/breaking-bedrock</guid><category><![CDATA[CSS]]></category><category><![CDATA[layout]]></category><category><![CDATA[React]]></category><category><![CDATA[CSS Frameworks]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Mon, 21 Nov 2022 18:03:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/J8X3iKaLheA/upload/v1669012876654/uEVloM62x.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few years ago, I started what ended up becoming the Bedrock Layout Primitive library. What began as a bit of a "revenge" driven project ended up becoming a passion. It resulted in an opportunity to <a target="_blank" href="https://www.newline.co/courses/composing-layouts-in-react">create a course on composing layouts in react</a> and speak at several conferences.  </p>
<p>In the meantime, Bedrock has continued to grow and evolve as a library. More primitives have been added, the doc site was moved to Storybook, and visual regression testing was added through chromatic. But the most significant addition out of all of the additions has to be the <code>@bedrock-layout/css</code> framework. Pretty much the same developer experience as the React library, using only CSS and no JavaScript.</p>
<h2 id="heading-things-have-changed">Things have changed</h2>
<p>At the same time that Bedrock Layout has been evolving, so has everything else. CSS and the three major browsers have hit some fantastic strides regarding CSS. They have been releasing new features on a much more consistent basis.</p>
<p>Another thing that has changed is that <code>styled-components</code> and CSS-in-JS tools, in general, have started to fall out as popular tools. There are many reasons why this is so. Nonetheless, building a library on top of <code>styled-components</code> means that Bedrock's adoption has been limited to only those projects that are willing to use <code>styled-components</code>.</p>
<p>In addition to this problem, maintaining both a CSS library and a React library built on <code>styled-components</code> means that I have to duplicate my effort every time I need to make a change. This increases the chance of divergences as well as just simple copy-paste errors.</p>
<p>Finally, to avoid breaking changes, we have maintained deprecated APIs even though they were no longer encouraged nor documented. All of these things have brought me to the conclusion that Bedrock needed to do a significant overhaul, or in other words, a breaking change.</p>
<h2 id="heading-announcing-the-new-and-improved-bedrock-layout-primitives">Announcing The New and Improved Bedrock Layout Primitives</h2>
<p>There are two significant changes that Bedrock Layout Primitives has made. The first is that Bedrock Layout no longer uses <code>styled-components</code>. It instead depends on its internal Bedrock Layout CSS, which you can install at <code>@bedrock-layout/css</code>. This now means you need to <a target="_blank" href="https://www.bedrock-layout.dev/?path=/docs/bedrock-layout-css-a-css-only-version--page">import the appropriate CSS files</a> for the primitives you are using or simply import them all:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">"@bedrock-layout/css"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"@bedrock-layout/css/lib/reset.css"</span>;
</code></pre>
<p>With this change, each package size has been cut in half and no longer has any runtime implications other than React itself. This makes Bedrock Layout great for any of your apps, no matter the React framework your team has chosen to adopt.</p>
<p>The other significant change has been that Bedrock Layout will no longer support its own spacing and sizes scheme. In the past, Bedrock's default spacing scheme was built on T-shirt sizes representing multiples of <code>1rem</code>. It worked fine, but it doesn't make sense for Bedrock to maintain another spacing scheme when there are so many better ones.  </p>
<p>With this new change, Bedrock has adopted a spacing and sizes theme based on <a target="_blank" href="https://open-props.style/#sizes">open-props</a>. Bedrock Layout now uses the following values:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-attr">space</span>:{
    <span class="hljs-attr">size000</span>: <span class="hljs-string">"-.5rem"</span>,
    <span class="hljs-attr">size00</span>: <span class="hljs-string">"-.25rem"</span>,
    <span class="hljs-attr">size1</span>: <span class="hljs-string">".25rem"</span>,
    <span class="hljs-attr">size2</span>: <span class="hljs-string">".5rem"</span>,
    <span class="hljs-attr">size3</span>: <span class="hljs-string">"1rem"</span>,
    <span class="hljs-attr">size4</span>: <span class="hljs-string">"1.25rem"</span>,
    <span class="hljs-attr">size5</span>: <span class="hljs-string">"1.5rem"</span>,
    <span class="hljs-attr">size6</span>: <span class="hljs-string">"1.75rem"</span>,
    <span class="hljs-attr">size7</span>: <span class="hljs-string">"2rem"</span>,
    <span class="hljs-attr">size8</span>: <span class="hljs-string">"3rem"</span>,
    <span class="hljs-attr">size9</span>: <span class="hljs-string">"4rem"</span>,
    <span class="hljs-attr">size10</span>: <span class="hljs-string">"5rem"</span>,
    <span class="hljs-attr">size11</span>: <span class="hljs-string">"7.5rem"</span>,
    <span class="hljs-attr">size12</span>: <span class="hljs-string">"10rem"</span>,
    <span class="hljs-attr">size13</span>: <span class="hljs-string">"15rem"</span>,
    <span class="hljs-attr">size14</span>: <span class="hljs-string">"20rem"</span>,
    <span class="hljs-attr">size15</span>: <span class="hljs-string">"30rem"</span>,
  },
  <span class="hljs-attr">sizes</span>: {
    <span class="hljs-attr">sizeContent1</span>: <span class="hljs-string">"20ch"</span>,
    <span class="hljs-attr">sizeContent2</span>: <span class="hljs-string">"45ch"</span>,
    <span class="hljs-attr">sizeContent3</span>: <span class="hljs-string">"60ch"</span>,
    <span class="hljs-attr">sizeHeader1</span>: <span class="hljs-string">"20ch"</span>,
    <span class="hljs-attr">sizeHeader2</span>: <span class="hljs-string">"25ch"</span>,
    <span class="hljs-attr">sizeHeader3</span>: <span class="hljs-string">"35ch"</span>,
    <span class="hljs-attr">sizeXxs</span>: <span class="hljs-string">"240px"</span>,
    <span class="hljs-attr">sizeXs</span>: <span class="hljs-string">"360px"</span>,
    <span class="hljs-attr">sizeSm</span>: <span class="hljs-string">"480px"</span>,
    <span class="hljs-attr">sizeMd</span>: <span class="hljs-string">"768px"</span>,
    <span class="hljs-attr">sizeLg</span>: <span class="hljs-string">"1024px"</span>,
    <span class="hljs-attr">sizeXl</span>: <span class="hljs-string">"1440px"</span>,
    <span class="hljs-attr">sizeXxl</span>: <span class="hljs-string">"1920px"</span>,
  }
}
</code></pre>
<p>In addition, some other breaking but insignificant changes have been that Bedrock has dropped the use of <code>prop-types</code> and uses only named exports for all the packages. Once again, not substantial, but breaking nonetheless.</p>
<h2 id="heading-what-has-really-changed">What has really changed?</h2>
<p>Not as much as it seems. Bedrock still works the same. It still helps you compose complex layouts from simple layout primitives.  </p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Hero</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Stack</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Inline</span>&gt;</span>{/* */}<span class="hljs-tag">&lt;/<span class="hljs-name">Inline</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Split</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Cover</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Stack</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{/* */}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{/* */}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Inline</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>{/* */}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>{/* */}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Inline</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Stack</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Cover</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Frame</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">img</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Frame</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Split</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Stack</span>&gt;</span></span>
  );
}
</code></pre>
<p>You can still bring your own spacing and sizing scheme via ThemeProvider and declaration merging:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { ThemeProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'@bedrock-layout/spacing-constants'</span>;

<span class="hljs-keyword">declare</span> <span class="hljs-keyword">module</span> "@bedrock-layout/spacing-constants" {
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> DefaultTheme {
    space: {
      <span class="hljs-string">"0x"</span>: <span class="hljs-built_in">number</span>;
      <span class="hljs-string">"1x"</span>: CSSLength;
      <span class="hljs-string">"3x"</span>: CSSLength;
    };
  }
}

<span class="hljs-keyword">const</span> space = {
    <span class="hljs-string">"0x"</span>: <span class="hljs-number">0</span>,
    <span class="hljs-string">"1x"</span>:<span class="hljs-string">'45px'</span>,
    <span class="hljs-string">"3x"</span>:<span class="hljs-string">'100ch'</span>
}

&lt;ThemeProvider theme={{ space }}&gt;
    &lt;Stack gutter=<span class="hljs-string">"1x"</span>&gt;
     {...}
    &lt;/Stack&gt;
&lt;/ThemeProvider&gt;;
</code></pre>
<p>You can also still provide values directly into the size and spacing values as usual:</p>
<pre><code class="lang-typescript">&lt;Stack gutter=<span class="hljs-string">"var(--size-3)"</span>&gt;
    &lt;Split gutter=<span class="hljs-string">'2rem'</span> minItemWidth=<span class="hljs-string">"30ch"</span> switchAt=<span class="hljs-string">"var(--size-content-1)"</span>&gt;
        {<span class="hljs-comment">/* ... */</span>}
   &lt;/Split&gt;
&lt;/Stack&gt;
</code></pre>
<p>It just does all this better under the hood than it used to.</p>
<p>Check out this code pen and play around with it yourself: https://codesandbox.io/s/bedrock-layout-ts-template-64xwz?file=/src/index.tsx</p>
<h2 id="heading-what-is-on-the-horizon">What is on the horizon?</h2>
<p>A significant initiative we have going forward is translating all the docs into as many languages as possible. With the help of a contributor, Carlos Cabrera, the landing page has been translated into Spanish. I want to put in the work and make it easier for future contributors to solve or fix the translation of any of the pages on the doc site.</p>
<p>I also would like to do more to bring the CSS Framework front and center and less as a second-class citizen.</p>
<p>I also feel that there needs to be more examples and recipes for using Bedrock Layout. If you would like to help out with any of these initiatives, <a target="_blank" href="https://www.bedrock-layout.dev/?path=/docs/overview-contributing--page">please look at contributing.</a></p>
]]></content:encoded></item><item><title><![CDATA[The Power of Maybe in TypeScript]]></title><description><![CDATA[In a perfect world, every function and every API we work with would have one clear type that always gets returned. Unfortunately, we don't live in a perfect world. In the real world, the functions and APIs we use might not have something to return to...]]></description><link>https://non-traditional.dev/the-power-of-maybe-in-typescript</link><guid isPermaLink="true">https://non-traditional.dev/the-power-of-maybe-in-typescript</guid><category><![CDATA[Effective Typescripte]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Wed, 31 Aug 2022 21:47:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/RSsqjpezn6o/upload/v1661976812012/XZhFt078B.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In a perfect world, every function and every API we work with would have one clear type that always gets returned. Unfortunately, we don't live in a perfect world. In the real world, the functions and APIs we use might not have something to return to use. We might get nothing back. For this reason, I have created a few utilities in TypeScript that I bring in pretty much any project I work on. These utilities all build on a powerful concept called the <code>Maybe</code>.</p>
<p>What is a <code>Maybe</code>? I was first introduced to a <a target="_blank" href="https://guide.elm-lang.org/error_handling/maybe.html"><code>Maybe</code></a> when exploring the <a target="_blank" href="https://elm-lang.org">Elm programming language</a>. The docs at Elm describe a <code>Maybe</code> best. This is what their docs say: "This is a type with two variants. You either have <code>Nothing</code> or you have <code>Just</code> a value."</p>
<p>That sounds simple enough, right? It either is something, or it is nothing. Well, that is where the JavaScript world makes things even more complicated. JavaScript doesn't just have a single <code>Nothing</code> type like many languages. Instead, it has two ways to represent <code>Nothing</code>: <code>null</code> and <code>undefined</code>. To take advantage of the concept of a <code>Maybe</code>, we need to simplify our <code>Nothing</code> states as either <code>null</code> or <code>undefined</code>.</p>
<p>First, we need to decide between the two. Because of the complicated history of <code>null</code> and the <code>typeof</code> bug that was introduced in the early drafts of JavaScript, I recommend that you embrace <code>undefined</code> as your <code>Nothing</code> state of choice. (If you want to read more about the bug, <a target="_blank" href="https://dev.to/_ravo_lution/why-typeof-null-is-object-181">there is a nice article by Sourav Debnath about the typeof null bug</a>)</p>
<p>That's well and good for the code you write, but what about other people's code? Many browser APIs return <code>null</code> for their <code>Nothing</code> state and other 3rd party libraries. What do you do about them?</p>
<p>What we need to do is convert the output from these APIs into a <code>Maybe</code>. I've created a simple, yet powerful utility that does just that:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">convertToMaybe</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">return</span> value ?? <span class="hljs-literal">undefined</span>;
}
</code></pre>
<p>This one-line function is made very simple using the <a target="_blank" href="https://non-traditional.dev/80-cleaner-javascript-code-using-optional-chaining-and-nullish-coalescing-3fb1d1df3867">nullish coalescing operator</a>. Let's break it down. First, if the value passed in is neither <code>null</code> nor <code>undefined</code>, it will return the value passed in. If the value is <code>null</code> or <code>undefined</code>, however, it will return the value on the right side of the <code>??</code>, which in our case is <code>undefined</code>. This guarantees that no matter what value we pass in, it will never return a <code>null</code>.</p>
<p>That sounds great in JavaScript, but I rarely write in plain JavaScript anymore. Most of my projects use TypeScript. Luckily there isn't much more we need to do to make this work well in TypeScript.</p>
<p>First, let's create our TypeScript Utility type:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Maybe&lt;T&gt; = NonNullable&lt;T&gt; | <span class="hljs-literal">undefined</span>;
</code></pre>
<p>Here we are creating a Generic Type called <code>T</code>. If you are unfamiliar with Generics, Generics act as a placeholder for a future type not yet decided. Generics let us pass in a type, much like how we pass arguments to a function. We are then using the Generic <code>T</code> to pass into the <code>NonNullable</code> type, which basically ensures that <code>T</code> can't be <code>null</code> or <code>undefined</code>. We are then using the union type operator, <code>|</code>, to also allow <code>undefined</code> as an allowed value.</p>
<p>Simply put, The <code>Maybe</code> of any type will either be that type or <code>undefined</code> but never null. A <code>Maybe&lt;number&gt;</code>, for example, will be either <code>number</code> or <code>undefined</code>. The <code>Maybe&lt;null&gt;</code>, however, can only be <code>undefined</code> because <code>null</code> is not allowed.</p>
<p>Now that we have defined our <code>Maybe</code> utility type, let's update our function:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">convertToMaybe</span>&lt;<span class="hljs-title">T</span> <span class="hljs-title">extends</span> <span class="hljs-title">unknown</span>&gt;(<span class="hljs-params">value: T</span>): <span class="hljs-title">Maybe</span>&lt;<span class="hljs-title">T</span>&gt; </span>{
  <span class="hljs-keyword">return</span> value ?? <span class="hljs-literal">undefined</span>;
}
</code></pre>
<p>In the above function, we added another Generic. We are not just defining a generic type of <code>T</code>, but we are also requiring that it extend the <code>unknown</code> type. And then we are saying our <code>value</code> parameter must be of type <code>T</code> and that the return value from the function will be a <code>Maybe&lt;T&gt;</code>.</p>
<p>I know you are probably asking, "Why are we going through all that extra boilerplate?" This way, TypeScript can infer the types based on the type of the value passed into the arguments. Now we can be sure that any value we are given is a <code>Maybe</code> value. If you have TypeScript, it will make you write defensive coding to ensure you don't have an empty value. Even if you are using JavaScript, the function will help you remember that the value I am getting back from the function might be <code>undefined</code> and I need to write defensive coding to protect myself.</p>
<p>Using <code>Maybe</code> values in your code is very powerful. Your code will be stronger and more resilient to empty values and allow you to fail gracefully in a state you can control.</p>
]]></content:encoded></item><item><title><![CDATA[An Intro to Solid.js for React Developers]]></title><description><![CDATA[In the 2021 state of JS survey result, solid.js, in its debut appearance, surprised many by jumping straight to the top of the satisfaction score. It beat out not just React but Svelte, the 2020 satisfaction leader. While React still maintains a sign...]]></description><link>https://non-traditional.dev/an-intro-to-solidjs-for-react-developers</link><guid isPermaLink="true">https://non-traditional.dev/an-intro-to-solidjs-for-react-developers</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[React]]></category><category><![CDATA[solid]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[theme]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Thu, 12 May 2022 20:43:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/CcO438ezU80/upload/v1652387962045/0BnSMjNm3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the 2021 state of JS survey result, solid.js, in its debut appearance, surprised many by jumping straight to the top of the satisfaction score. It beat out not just React but Svelte, the 2020 satisfaction leader. While React still maintains a significant market share, ignoring solid.js would be a mistake.</p>
<h2 id="heading-solid-feels-very-familiar-to-react-developers">Solid feels very familiar to react developers</h2>
<p>Let's look at this arbitrary counter app written in solid.js:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Counter</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = createSignal(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>The current count is: {count()}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount((x) =&gt; x + 1)}&gt;Plus<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>I am confident that any React developer can understand everything in the above component, despite never seeing solid.js before. This familiarity is because solid.js has an API familiar to React Developers. For one thing, solid.js utilizes JSX, which means elements and components can be composed in many of the same familiar ways that React developers have built an intuition for. For example, we can make this arbitrary Welcome component using just our intuition from building React Apps:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Welcome</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Welcome, {props.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
}
</code></pre>
<p>Solid.js also utilizes primitives with an API that is very similar to how one would use React hooks. The API of many of solid's reactive primitives are almost identical to their React Hook counterparts.</p>
<p>It's important to point out that solid.js is not attempting to follow React's API one-to-one. You cannot take a React app and start using it in solid.js. It does, however, have an API that is familiar to your average React developer, which makes the learning curve much nicer.</p>
<h2 id="heading-its-all-about-the-primitives">It's all about the primitives</h2>
<p>Despite its superficial similarities, what makes solid.js unique is the ways that it is not like React. One of those ways is that, unlike React, the component is not the foundation of solid.js apps. Solid.js proudly describes its components as "vanishing components." Components are helpful for code organization and cease to exist once the initial render occurs.</p>
<p>For solid.js, it's all about the primitives. Solid.js has a suite of "fine-grained reactive primitives." These primitives can feel very similar to React Hooks, but they are not hooks. In React, hooks are dependent upon the React component lifecycle and require you to have at least a rudimentary understanding of the Virtual DOM and the React render lifecycles. This dependency on the React lifecycle is why there are so many "rules of hooks" that you need to know to use them correctly. Let's take this React Component, for example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Counter</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">document</span>.title = <span class="hljs-string">`The current count is: <span class="hljs-subst">${count}</span>`</span>;
  }, [count]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>The current count is: {count}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount((x) =&gt; x + 1)}&gt;Plus<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Despite how simple this component is, there are several rules you need to remember, and forgetting any of them can cause unwanted problems. Solid's reactive primitives, on the other hand, just work. They can be called conditionally, and they don't even need to be called in a component themselves. The above counter component can be rewritten in solid.js like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [count, setCount] = createSignal(<span class="hljs-number">0</span>);

createEffect(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">document</span>.title = <span class="hljs-string">`The current count is: <span class="hljs-subst">${count()}</span>`</span>;
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Counter</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>The current count is: {count()}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setCount((x) =&gt; x + 1)}&gt;Plus<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>We have moved all the reactive primitives outside of the component itself in the above component. We can do this because Solid's reactive primitives themselves, not the components, are what solid.js is built on and where the "magic" happens.</p>
<h2 id="heading-reactivity-vs-virtual-dom">Reactivity VS Virtual DOM</h2>
<p>Like many popular frameworks, React is built on the concept of a "Virtual DOM." A virtual DOM is an in-memory representation of the actual DOM. The idea is that doing things in memory is less expensive than working with the actual DOM, so one can run and re-run components multiple times, making changes to this virtual DOM. Only if there are actual differences between the virtual DOM and the real DOM will React reconcile those changes from the virtual DOM to the actual DOM. You are literally hooking into the React Virtual DOM Lifecycle when you use hooks.</p>
<p>Solid.js, on the other hand, depends on "fine-grained" reactivity. When you write a JSX expression that relies on a reactive signal, for example, only the part of the JSX that depends on that signal's value is wrapped in a function that is re-run if that signal changes. The same goes for effects run in the <code>createEffect</code> primitive. If the effect has a dependency on one or more reactive values, it will be re-run only if the reactive value changes. There is no need for a dependency array since solid knows in advance if the value can be changed and will re-run only those effects that depend on the changed reactive values.</p>
<p>This is why solid components are "vanishing," and reactive primitives can be called outside of the component. After the initial render, only those fine-grained parts of the app will continue to exist.</p>
<h2 id="heading-gotchas-coming-from-react">Gotchas coming from React</h2>
<p>This difference in how the two frameworks work under the hood can lead to two of the biggest "gotchas" that React developers fall into when starting with solid.js. The first gotcha is you need to re-teach yourself that components don't ever get re-run. Those things that we have taught ourselves that we should (and shouldn't) do in a React component no longer apply in Solid.js. We don't need hooks like <code>useCallback</code> and <code>useRef</code>, because the component never re-runs. Instead, we can just assign them to variables like any other JavaScript code we write:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyForm</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-comment">/* handl submit */</span>
  };

  <span class="hljs-keyword">let</span> myInput;
  <span class="hljs-comment">// use onMount or createEffect to read after connected to DOM</span>
  onMount(<span class="hljs-function">() =&gt;</span> myInput.focus());

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">onSubmit</span>=<span class="hljs-string">{handleSubmit}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{myInput}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span></span>
  );
}
</code></pre>
<p>The second is that you can break the fine-grained reactivity if you destructure the props. The props object may or may not have reactive values in them. By destructuring them, that reactivity can be lost. So instead of writing code like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Greeting</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">const</span> { greeting, name } = props;
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>
      {greeting} {name}
    <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span></span>
  );
}
</code></pre>
<p>It would be best if you wrote it like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Greeting</span>(<span class="hljs-params">props</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>
      {props.greeting} {props.name}
    <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span></span>
  );
}
</code></pre>
<p>Or you can utilize solid's <code>mergeProps</code> or <code>splitProps</code> utility functions, which allow you to merge or split objects with reactive values without breaking reactivity.</p>
<p>When React was introduced, it challenged the best practices of the day. That challenge has had a lasting impact on how we write web applications. Solid is here to continue to push us in that same direction that React started.</p>
]]></content:encoded></item><item><title><![CDATA[Modernizing JavaScript Code: CSV/Table Manipulation]]></title><description><![CDATA[In previous posts, we have worked through some of the code examples of the book Functional JavaScript. I'm going to go over the final example from Chapter 1 where the author shows how to parse a CSV file into a table, or more accurately an array of a...]]></description><link>https://non-traditional.dev/modernizing-javascript-code-csvtable-manipulation</link><guid isPermaLink="true">https://non-traditional.dev/modernizing-javascript-code-csvtable-manipulation</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Fri, 25 Feb 2022 02:30:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/u3ajSXhZM_U/upload/v1645727812198/YYHLm-df5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In previous posts, we have worked through some of the code examples of the book Functional JavaScript. I'm going to go over the final example from Chapter 1 where the author shows how to parse a CSV file into a table, or more accurately an array of arrays of strings, that we can then use functions to manipulate into new tables with the data grouped and ordered differently.</p>
<h2 id="heading-the-original-code">The Original Code</h2>
<p>Let's start by looking at the raw code examples from the book:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//  people.csv</span>
<span class="hljs-comment">//  Name,   Age, Hair</span>
<span class="hljs-comment">//  Merble, 35,  red</span>
<span class="hljs-comment">//  Bob,    64,  blonde</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">lameCSV</span>(<span class="hljs-params">str</span>) </span>{
  <span class="hljs-keyword">return</span> _.reduce(
    str.split(<span class="hljs-string">"\n"</span>),
    <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">table, row</span>) </span>{
      table.push(
        _.map(row.split(<span class="hljs-string">","</span>), <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">c</span>) </span>{
          <span class="hljs-keyword">return</span> c.trim();
        })
      );
      <span class="hljs-keyword">return</span> table;
    },
    []
  );
}

<span class="hljs-keyword">var</span> peopleTable = lameCSV(peoplsCSV);
<span class="hljs-comment">// [</span>
<span class="hljs-comment">//     ['Name','Age','Hair'],</span>
<span class="hljs-comment">//     ['Merble','35','red'],</span>
<span class="hljs-comment">//     ['Bob','64','blonde'],</span>
<span class="hljs-comment">// ]</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectNames</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">return</span> _.rest(_.map(arr, _.first));
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectAges</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">return</span> _.rest(_.map(arr, second));
}

<span class="hljs-keyword">var</span> zipped = _.zip(selectNames(peopleTable), selectAges(peopleTable));

<span class="hljs-built_in">console</span>.log(zipped);
<span class="hljs-comment">// [["Merble","35"], ["Bob","64"]]</span>
</code></pre>
<p>In the above code, we have a function called <code>lameCSV</code> that parses a CSV file into an array of string arrays. We then have two helper functions, <code>selectNames</code> and <code>selectAges</code> that both do similar things. They both map over the array to retrieve either the first or second item in each array (<a target="_blank" href="https://non-traditional.dev/modernizing-examples-the-nth-function">we talked about the second function in a previous post</a>). After that, they both use the <code>_.rest</code> utility from underscore.js to remove the first item in the array and return the rest.</p>
<p>Finally, we use both of those select functions with the <code>_.zip</code> utility to merge the results back together.</p>
<h2 id="heading-modernizing">Modernizing</h2>
<p>To modernize, let's start off with some low-hanging fruit. First, we can remove the <code>var</code> variable declarations and use either <code>let</code> or <code>const</code>. It is also good practice to use arrow functions as callbacks, so let's use those when appropriate. We no longer need the <code>_.map</code> and <code>_.reduce</code> functions so we can move those over to native array functions. In addition, I prefer to avoid mutating arrays, so let's change our <code>table.push</code> to <code>table.concat</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">lameCSV</span>(<span class="hljs-params">str</span>) </span>{
  <span class="hljs-keyword">return</span> str
    .split(<span class="hljs-string">"\n"</span>)
    .reduce(
      <span class="hljs-function">(<span class="hljs-params">table, row</span>) =&gt;</span> table.concat(row.split(<span class="hljs-string">","</span>).map(<span class="hljs-function">(<span class="hljs-params">c</span>) =&gt;</span> c.trim())),
      []
    );
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectNames</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">return</span> _.rest(arr.map(first));
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectAges</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">return</span> _.rest(arr.map(second));
}
</code></pre>
<p>The next thing we can do to modernize is move away from using the <code>_.rest</code> function from underscore. In modern JavaScript we can use the rest parameter to do the exact same thing:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectNames</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">const</span> [, ...rest] = arr.map(first);
  <span class="hljs-keyword">return</span> rest;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectAges</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">const</span> [, ...rest] = arr.map(second);
  <span class="hljs-keyword">return</span> rest;
}
</code></pre>
<p>While we are talking about removing underscore functions, lets make our own zip functions:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">zip</span>(<span class="hljs-params">...args</span>) </span>{
  <span class="hljs-keyword">const</span> longestLength = <span class="hljs-built_in">Math</span>.max(...args.map(<span class="hljs-function">(<span class="hljs-params">arg</span>) =&gt;</span> arg.length));

  <span class="hljs-keyword">const</span> arrayOfIndexes = <span class="hljs-built_in">Array</span>.from(<span class="hljs-built_in">Array</span>(longestLength).keys());

  <span class="hljs-keyword">return</span> arrayOfIndexes.map(<span class="hljs-function">(<span class="hljs-params">i</span>) =&gt;</span> args.map(<span class="hljs-function">(<span class="hljs-params">array</span>) =&gt;</span> nth(array, i)));
}
</code></pre>
<p>In our <code>zip</code> function, first, we are collecting all the arrays passed in under a single array called <code>args</code> using the rest parameter. From there we use the <code>args</code> to find the length of the longest array in the args. After that, we create an array of indexes with this code: <code>Array.from(Array(longestLength).keys())</code>. What this does is create an array with the same length as the <code>longestLength</code>. By calling the <code>keys</code> method on that array we then get an iterable of all the indexes of that array. Since it is an iterable and not an array itself, we wrap the whole thing in <code>Array.from</code> to convert it back to an array.</p>
<p>Finally, the last thing we do is map over the <code>arrayOfIndexes</code> and use that index to create an array of all the values at that index in each array.</p>
<p>So here is the final version of the modernized code:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//  people.csv</span>
<span class="hljs-comment">//  Name,   Age, Hair</span>
<span class="hljs-comment">//  Merble, 35,  red</span>
<span class="hljs-comment">//  Bob,    64,  blonde</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">lameCSV</span>(<span class="hljs-params">str</span>) </span>{
  <span class="hljs-keyword">return</span> str
    .split(<span class="hljs-string">"\n"</span>)
    .reduce(
      <span class="hljs-function">(<span class="hljs-params">table, row</span>) =&gt;</span> table.concat(row.split(<span class="hljs-string">","</span>).map(<span class="hljs-function">(<span class="hljs-params">c</span>) =&gt;</span> c.trim())),
      []
    );
}

<span class="hljs-keyword">var</span> peopleTable = lameCSV(peoplsCSV);
<span class="hljs-comment">// [</span>
<span class="hljs-comment">//     ['Name','Age','Hair'],</span>
<span class="hljs-comment">//     ['Merble','35','red'],</span>
<span class="hljs-comment">//     ['Bob','64','blonde'],</span>
<span class="hljs-comment">// ]</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectNames</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">const</span> [, ...rest] = arr.map(first);
  <span class="hljs-keyword">return</span> rest;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectAges</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">const</span> [, ...rest] = arr.map(second);
  <span class="hljs-keyword">return</span> rest;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">zip</span>(<span class="hljs-params">...args</span>) </span>{
  <span class="hljs-keyword">const</span> longestLength = <span class="hljs-built_in">Math</span>.max(...args.map(<span class="hljs-function">(<span class="hljs-params">arg</span>) =&gt;</span> arg.length));

  <span class="hljs-keyword">const</span> arrayOfIndexes = <span class="hljs-built_in">Array</span>.from(<span class="hljs-built_in">Array</span>(longestLength).keys());

  <span class="hljs-keyword">return</span> arrayOfIndexes.map(<span class="hljs-function">(<span class="hljs-params">i</span>) =&gt;</span> args.map(<span class="hljs-function">(<span class="hljs-params">array</span>) =&gt;</span> nth(array, i)));
}

<span class="hljs-keyword">var</span> zipped = zip(selectNames(peopleTable), selectAges(peopleTable));

<span class="hljs-built_in">console</span>.log(zipped);
<span class="hljs-comment">// [["Merble","35"], ["Bob","64"]]</span>
</code></pre>
<h2 id="heading-now-with-typescript">Now with TypeScript</h2>
<p>First let's type our <code>lameCSV</code> function:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Table = <span class="hljs-built_in">string</span>[][];

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">lameCSV</span>(<span class="hljs-params">str: <span class="hljs-built_in">string</span></span>): <span class="hljs-title">Table</span> </span>{
  <span class="hljs-keyword">return</span> str
    .split(<span class="hljs-string">"\n"</span>)
    .reduce&lt;Table&gt;(
      <span class="hljs-function">(<span class="hljs-params">table, row</span>) =&gt;</span> table.concat(row.split(<span class="hljs-string">","</span>).map(<span class="hljs-function">(<span class="hljs-params">c</span>) =&gt;</span> c.trim())),
      []
    );
}
</code></pre>
<p>It takes a string, so that is easy to type. It technically returns an array of string arrays, which is <code>string[][]</code>, but often it is nice to give a type like that a name that has more meaning. In our case, we have created a type <code>Table</code> that is technically a <code>string[][]</code> under the hood. This not only gives the return value of this function more meaning, it gives our other functions meaning as well. We can type our select functions like this:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectNames</span>(<span class="hljs-params">arr: Table</span>) </span>{
  <span class="hljs-keyword">const</span> [, ...rest] = arr.map(first);
  <span class="hljs-keyword">return</span> rest;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectAges</span>(<span class="hljs-params">arr: Table</span>) </span>{
  <span class="hljs-keyword">const</span> [, ...rest] = arr.map(second);
  <span class="hljs-keyword">return</span> rest;
}
</code></pre>
<p>This makes it more clear that these functions are intended to be paired with the <code>lameCSV</code> function since their input is the output of the <code>lameCSV</code> function is their input. Unlike some type systems, TypeScript is a structural type system. This means that you can still pass in anything that happens to have the same type as <code>string[][]</code> to these functions and it will work. That said, by giving it the type <code>Table</code> you are using your types to do a form of domain modeling, which simply put is documenting the relationship between the parts of your code.</p>
<p>The final thing we need to do is type our <code>zip</code> function. Let's start with the finished version and then let's explain it:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">zip</span>&lt;<span class="hljs-title">T</span> <span class="hljs-title">extends</span> <span class="hljs-title">Array</span>&lt;<span class="hljs-title">unknown</span>[]&gt;&gt;(<span class="hljs-params">...args: T</span>): <span class="hljs-title">T</span>[<span class="hljs-title">number</span>][] </span>{
  <span class="hljs-keyword">const</span> longestLength = <span class="hljs-built_in">Math</span>.max(...args.map(<span class="hljs-function">(<span class="hljs-params">arg</span>) =&gt;</span> arg.length));

  <span class="hljs-keyword">const</span> arrayOfIndexes = <span class="hljs-built_in">Array</span>.from(<span class="hljs-built_in">Array</span>(longestLength).keys());

  <span class="hljs-keyword">return</span> arrayOfIndexes.map(<span class="hljs-function">(<span class="hljs-params">i</span>) =&gt;</span> args.map(<span class="hljs-function">(<span class="hljs-params">array</span>) =&gt;</span> nth(array, i)));
}
</code></pre>
<p>In the above code, we are declaring that the <code>args</code> are of type <code>T</code> and that <code>T extends Array&lt;unknown[]&gt;</code>. This allows TypeScript to do two things. First, it will enforce that all the arguments passed in are arrays. The other thing that it will do is infer the type from the arrays passed. This brings us to the return type. We are declaring that the return value is <code>T[number][]</code>, which means that the return will be an array of whatever type is at any index of <code>T</code>. So now our final typescript version looks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//  people.csv</span>
<span class="hljs-comment">//  Name,   Age, Hair</span>
<span class="hljs-comment">//  Merble, 35,  red</span>
<span class="hljs-comment">//  Bob,    64,  blonde</span>

type Table = string[][];

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">lameCSV</span>(<span class="hljs-params">str: string</span>): <span class="hljs-title">Table</span> </span>{
  <span class="hljs-keyword">return</span> str
    .split(<span class="hljs-string">"\n"</span>)
    .reduce&lt;Table&gt;(
      <span class="hljs-function">(<span class="hljs-params">table, row</span>) =&gt;</span> table.concat(row.split(<span class="hljs-string">","</span>).map(<span class="hljs-function">(<span class="hljs-params">c</span>) =&gt;</span> c.trim())),
      []
    );
}

<span class="hljs-keyword">var</span> peopleTable = lameCSV(peoplsCSV);
<span class="hljs-comment">// [</span>
<span class="hljs-comment">//     ['Name','Age','Hair'],</span>
<span class="hljs-comment">//     ['Merble','35','red'],</span>
<span class="hljs-comment">//     ['Bob','64','blonde'],</span>
<span class="hljs-comment">// ]</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectNames</span>(<span class="hljs-params">arr: Table</span>) </span>{
  <span class="hljs-keyword">const</span> [, ...rest] = arr.map(first);
  <span class="hljs-keyword">return</span> rest;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">selectAges</span>(<span class="hljs-params">arr: Table</span>) </span>{
  <span class="hljs-keyword">const</span> [, ...rest] = arr.map(second);
  <span class="hljs-keyword">return</span> rest;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">zip</span>&lt;<span class="hljs-title">T</span> <span class="hljs-title">extends</span> <span class="hljs-title">Array</span>&lt;<span class="hljs-title">unknown</span>[]&gt;&gt;(<span class="hljs-params">...args: T</span>): <span class="hljs-title">T</span>[<span class="hljs-title">number</span>][] </span>{
  <span class="hljs-keyword">const</span> longestLength = <span class="hljs-built_in">Math</span>.max(...args.map(<span class="hljs-function">(<span class="hljs-params">arg</span>) =&gt;</span> arg.length));

  <span class="hljs-keyword">const</span> arrayOfIndexes = <span class="hljs-built_in">Array</span>.from(<span class="hljs-built_in">Array</span>(longestLength).keys());

  <span class="hljs-keyword">return</span> arrayOfIndexes.map(<span class="hljs-function">(<span class="hljs-params">i</span>) =&gt;</span> args.map(<span class="hljs-function">(<span class="hljs-params">array</span>) =&gt;</span> nth(array, i)));
}

<span class="hljs-keyword">var</span> zipped = zip(selectNames(peopleTable), selectAges(peopleTable));

<span class="hljs-built_in">console</span>.log(zipped);
<span class="hljs-comment">// [["Merble","35"], ["Bob","64"]]</span>
</code></pre>
<p>With that, we have officially modernized all the examples from chapter 1. I hope you enjoyed this series so far and that you will keep looking out for future posts on this.</p>
]]></content:encoded></item><item><title><![CDATA[Using JavaScript Proxies to Make Sorting Arrays Safe]]></title><description><![CDATA[Array methods can be grouped into two categories: mutating and non-mutating methods. Methods such as push, pop, and splice are mutating because they change the array they are called on, for example:
const myArr = [1, 2, 3];

myArr.push(4);
// myArr =...]]></description><link>https://non-traditional.dev/using-javascript-proxies-to-make-sorting-arrays-safe</link><guid isPermaLink="true">https://non-traditional.dev/using-javascript-proxies-to-make-sorting-arrays-safe</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[proxy]]></category><category><![CDATA[array methods]]></category><category><![CDATA[sorting]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Fri, 04 Feb 2022 19:52:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/yFlC156ZTCY/upload/v1643957466981/EQ7sYSRN7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Array methods can be grouped into two categories: mutating and non-mutating methods. Methods such as <code>push</code>, <code>pop</code>, and <code>splice</code> are mutating because they change the array they are called on, for example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myArr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];

myArr.push(<span class="hljs-number">4</span>);
<span class="hljs-comment">// myArr = [1, 2, 3, 4]</span>

<span class="hljs-keyword">const</span> popped = myArr.pop();
<span class="hljs-comment">/**
 * popped = 4
 * myArr = [1, 2, 3]
 */</span>

<span class="hljs-keyword">const</span> spliced = myArr.splice(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>);
<span class="hljs-comment">/**
 * spliced = 2
 * myArr = [1, 3]
 */</span>
</code></pre>
<p>On the other hand, methods like <code>map</code>, <code>filter</code>, and <code>slice</code> are non-mutating because they do not change the array they are called on. Instead, they create a new array from them, like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> myArr = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];

<span class="hljs-keyword">const</span> myArrPlusOne = myArr.map(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x + <span class="hljs-number">1</span>);
<span class="hljs-comment">// myArrPlusOne = [2, 3, 4]</span>

<span class="hljs-keyword">const</span> onlyOdd = myArr.filter(<span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> x % <span class="hljs-number">2</span> === <span class="hljs-number">1</span>);
<span class="hljs-comment">// onlyOdd = [1, 3]</span>

<span class="hljs-keyword">const</span> sliced = myArr.slice(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>);
<span class="hljs-comment">// sliced = [2]</span>

<span class="hljs-built_in">console</span>.log(myArr);
<span class="hljs-comment">// [1, 2, 3]</span>
</code></pre>
<p>However, there is one method that is often mistaken as a non-mutating method but is mutating. This method is the <code>sort</code> method. The sort method takes a comparator function and sorts the array called on. What makes it "feel" like a non-mutating array is that it also returns the now sorted array:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> unsortedArr = [<span class="hljs-number">5</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>];

<span class="hljs-keyword">const</span> sortedArr = unsortedArr.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a - b);

<span class="hljs-built_in">console</span>.log(unsortedArr);
<span class="hljs-comment">// [1, 2, 3, 4, 5]</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Object</span>.is(sortedArr, unsortedArr));
<span class="hljs-comment">// true</span>
</code></pre>
<p>By returning itself, it allows us to chain the <code>sort</code> method among other array methods. Unfortunately, this means that we can accidentally mutate an array we never intended to:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> clientIds = [<span class="hljs-number">5</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">3</span>];

<span class="hljs-keyword">const</span> sortedClients = clientIds
  .sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a - b) <span class="hljs-comment">//oops just mutated the clientIds array</span>
  .map(idToClientObject);
</code></pre>
<h2 id="heading-fixing-the-sort-method">"Fixing" the sort method</h2>
<p>Wouldn't it be great if we could "fix" the sort method so that it would return a sorted array without sorting the array it was called on? Well, we can, by using <code>Proxy</code> objects. <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy"><code>Proxy</code> objects</a> let you pass in a target object and object of handlers that define the behavior of the proxy object. It will then return a new object that has this new behavior. Let's start by creating a function that will take an array and return a new proxy wrapped array:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createSafeSorter</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(arr, {});
}
</code></pre>
<p>We can trap many behaviors, but the handler we want to define is the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/get"><code>get</code> handler</a>. The <code>get</code> handler is called whenever a property is retrieved from the target object. This includes when we call methods on the target. Knowing that, let's create our handler:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createSafeSorter</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(arr, {
    <span class="hljs-attr">get</span>: <span class="hljs-function">(<span class="hljs-params">target, prop, receiver</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (prop === <span class="hljs-string">"sort"</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">comparator</span>) =&gt;</span> [...target].sort(comparator);
      }

      <span class="hljs-keyword">return</span> <span class="hljs-built_in">Reflect</span>.get(target, prop, receiver);
    },
  });
}
</code></pre>
<p>In the above code, we assign a function to the <code>get</code> property of our handler object. This function accepts a <code>target</code>, which is the object passed into the proxy, a <code>prop</code> which is the name of the property that the code is trying to get, and the <code>receiver</code>, which is either the proxy or an object that inherits from the proxy (not necessary for what we are doing).</p>
<p>The handler checks if the <code>prop</code> is the <code>sort</code> method. If it is, it will return a new function that takes a comparator and uses that function to sort a copy of the original array. Otherwise, we pass the <code>target</code>, <code>prop</code>, and <code>receiver</code> to the <code>get</code> method of the <code>Reflect</code> object. <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect">The <code>Reflect</code> object is super simple</a>. It complements the <code>Proxy</code> objects in that it has static methods that you can create handlers for. Passing the arguments received in our handler function into the same method on the <code>Reflect</code> object will return the original value. That was a long way of saying everything else will work the same.</p>
<p>Now we can pass in an array and get back an array wrapped in a proxy that will use our safe sort method instead of the native sort method. Everything is excellent, right? We have one last thing we need to fix. We are copying the array and then sorting it in the above handler, but that new array is not wrapped in a proxy. This means that if we need to call sort again, we will end up mutating our new array, for example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> unsorted = createSafeSorter([<span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>]);

<span class="hljs-comment">// Works great</span>
<span class="hljs-keyword">const</span> lowToHigh = unsorted.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a - b);

<span class="hljs-comment">// Oops, we did it again</span>
<span class="hljs-keyword">const</span> highToLow = lowToHigh.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> b - a);
</code></pre>
<p>Luckily the solution is easy. We just need to do a little recursiveness and wrap our new sorted array in our <code>createSafeSorter</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createSafeSorter</span>(<span class="hljs-params">arr</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(arr, {
    <span class="hljs-attr">get</span>: <span class="hljs-function">(<span class="hljs-params">target, prop, receiver</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (prop === <span class="hljs-string">"sort"</span>) {
        <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">comparator</span>) =&gt;</span> createSafeSorter([...target].sort(comparator));
      }

      <span class="hljs-keyword">return</span> <span class="hljs-built_in">Reflect</span>.get(target, prop, receiver);
    },
  });
}
</code></pre>
<p>Now we can do this lot of code safely:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> unsorted = createSafeSorter([<span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>]);

<span class="hljs-comment">// Works great</span>
<span class="hljs-keyword">const</span> lowToHigh = unsorted.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a - b);

<span class="hljs-comment">// Also safe!!!</span>
<span class="hljs-keyword">const</span> highToLow = lowToHigh.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> b - a);
</code></pre>
<h2 id="heading-why-you-shouldnt-do-this">Why you shouldn't do this</h2>
<p>Now that I have spent a whole blog post on how to make your <code>sort</code> method safe and non-mutating, I am going to recommend that you don't do this in your codebase ever. If you do this, you and your team may know that the array being passed around uses a safe sort, but not everyone else does. Other people and third-party packages have written code based on the fact that <code>sort</code> is mutating. If you change that behavior, you can create so many unintended consequences. It is this exact reason why browsers will never fix the <code>typeof null === 'object'</code> bug. So much defensive code has been written around this fact that you would break the web if you "fixed" it. If you like, create a <code>safeSort</code> utility for your project and use that any time you sort:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">safeSort</span>(<span class="hljs-params">arr, comparator</span>) </span>{
  <span class="hljs-keyword">return</span> [...arr].sort(comparator);
}
</code></pre>
<p>Anyway, I hope you enjoyed this journey into using Proxy objects and why you shouldn't use them to "fix" the platform.</p>
]]></content:encoded></item><item><title><![CDATA[Using a Trie Data Structure in JavaScript]]></title><description><![CDATA[Since the beginning of the year, I have been working on my personalized CS degree. Currently, I am working on MIT Course 6-001, which is an intro to programming. Expectedly, the lectures haven't been anything new to me, but I have still learned new t...]]></description><link>https://non-traditional.dev/using-a-trie-data-structure-in-javascript</link><guid isPermaLink="true">https://non-traditional.dev/using-a-trie-data-structure-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[data structures]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Thu, 20 Jan 2022 07:48:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/boE2xft0cAo/upload/v1642653581918/2GNkHEP-M.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Since the beginning of the year, I have been working on <a target="_blank" href="https://non-traditional.dev/getting-a-computer-science-degree-in-2022">my personalized CS degree</a>. Currently, I am working on <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0001-introduction-to-computer-science-and-programming-in-python-fall-2016/">MIT Course 6-001</a>, which is an intro to programming. Expectedly, the lectures haven't been anything new to me, but I have still learned new things by adapting the problem sets written in python to TypeScript.</p>
<p>There is one problem set in particular that has tested my knowledge. In one of the problem sets, intended to help learn about looping, I wrote a solution using a trie data structure (pronounced "try"). Even though a regular student wouldn't know about this structure, I decided to use it to help me learn and understand it better. In the rest of this post, I will go over the trie data structure and its usefulness.</p>
<h2 id="heading-what-is-a-trie">What is a trie?</h2>
<p>A trie data structure is a data structure that is best used to optimize retrieving data. In fact, the name trie comes from the four letters in the middle of the word retrieval (reTRIEval). Simply put, a trie is a bunch of nested objects that efficiently store data.</p>
<p>The trie data structure is best understood with a use case. Let's say we want to have a list of current users on a website to search through. We want to show all valid users that start with what our user has typed so far as our user types. We could put it all in an array and search for it like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getNames</span>(<span class="hljs-params">namePart, validNames</span>)</span>{
    <span class="hljs-keyword">return</span> validNames.filter(<span class="hljs-function"><span class="hljs-params">name</span>=&gt;</span>\^rob\.test(name))
}
</code></pre>
<p>This is simple and easy to understand, but it can be rather inefficient to keep checking the entire array every time the user types a letter. This is especially true if the list of users becomes huge.</p>
<p>A trie takes advantage of the fact that we have overlapping string parts, and we can store them in a nested object that takes advantage of that. Let's say we have the following names: Sandy, Rex, Robert, Sara, Rob, and Sarah. We can put them in a trie that would look something like this diagram:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642659854720/b7Z5SMRGd.png" alt="trie diagram.png" /></p>
<p>Each node represents a letter, with special markers on those nodes representing the end of a name. You can already see how efficient this is. As soon as you type one letter, you throw away 25 possible paths. We continue to narrow down the possibilities rapidly for each letter, drastically reducing the number of options as we go.</p>
<p>To implement a trie in JavaScript with just the name <code>rex</code>, it would look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> trie = {
  <span class="hljs-attr">end</span>: <span class="hljs-literal">false</span>,
  <span class="hljs-attr">children</span>: {
    <span class="hljs-attr">r</span>: {
      <span class="hljs-attr">end</span>: <span class="hljs-literal">false</span>,
      <span class="hljs-attr">children</span>: {
        <span class="hljs-attr">e</span>: {
          <span class="hljs-attr">end</span>: <span class="hljs-literal">false</span>,
          <span class="hljs-attr">children</span>: {
            <span class="hljs-attr">x</span>: {
              <span class="hljs-attr">end</span>: <span class="hljs-literal">true</span>,
              <span class="hljs-attr">children</span>: {},
            },
          },
        },
      },
    },
  },
};
</code></pre>
<p>This may not be very readable for a human, but it is beneficial to write code around. To add a word, we can traverse the tree, adding new nodes as needed along the way. The same is true for finding words. One needs to traverse the tree, finding all the children nodes that the <code>end</code> property is <code>true</code></p>
<h2 id="heading-the-specific-problem">The specific problem</h2>
<p>I needed to check if a user's input was a valid word in an array of words in the problem set. Normally I would do something like <code>wordlist.includes(validWords)</code>. The problem is that once per word, a user can replace a vowel with the <code>*</code> wildcard character that could represent any vowel. In other words, <code>c*t</code> would match to <code>cat</code>, <code>cot</code>, or <code>cut</code>.</p>
<p>To do this with an array would be possible, but it would not be straightforward to read or write. Let's say we have converted the word list to a trie. We could easily write a lookup like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkIsValidWord</span>(<span class="hljs-params">word, trieNode</span>) </span>{
  <span class="hljs-keyword">if</span> (word === <span class="hljs-string">""</span>) <span class="hljs-keyword">return</span> trieNode.end;

  <span class="hljs-keyword">const</span> nextLetters = word[<span class="hljs-number">0</span>] === <span class="hljs-string">"*"</span> ? <span class="hljs-string">"aeiou"</span> : word[<span class="hljs-number">0</span>];
  <span class="hljs-keyword">const</span> remainingWord = word.substring(<span class="hljs-number">1</span>);

  <span class="hljs-keyword">const</span> defaultNode = { <span class="hljs-attr">end</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">children</span>: {} };

  <span class="hljs-keyword">return</span> nextLetters.split(<span class="hljs-string">""</span>).reduce(<span class="hljs-function">(<span class="hljs-params">validWordFound, char</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> nextNode = trieNode.children[char] ?? defaultNode;
    <span class="hljs-keyword">return</span> validWordFound || checkIsValidWord(remainingWord, nextNode);
  }, <span class="hljs-literal">false</span>);
}
</code></pre>
<p>The above function is a recursive function that takes a word and a trieNode. Since it is recursive, we start the function with a base case. If the string is empty, the <code>trieNode</code> passed in is the final node, and we can return the value at the <code>end</code> property.</p>
<p>If the word is not an empty string, then we do two things: grab the next character(s) to check and assign it to <code>nextLetters</code>. If the next character is <code>*</code>, we need to check the <code>aeiou</code> string. Otherwise, we check the next character. After that, we take the remaining part of the word as the next word to check. Otherwise, we will just check the next letter.</p>
<p>After that, we split the <code>nextLetters</code> string into an array of characters. We reduce that array of characters by checking if we have found a valid word yet, and if not, we call the <code>checkIsValidWord</code> function with the remaining characters and the node of the character we are checking.</p>
<p>By adopting a data structure design for what we want to do, we have made both an efficient and elegant solution for a potentially complicated problem.</p>
]]></content:encoded></item><item><title><![CDATA[Getting a Computer Science Degree in 2022]]></title><description><![CDATA[I don't have a CS degree. In fact, I have a degree in Business Administration. Not a bad degree, but not something that directly helps me in my day-to-day job as a software engineer. This is perfectly fine. When it comes to job qualifications, coding...]]></description><link>https://non-traditional.dev/getting-a-computer-science-degree-in-2022</link><guid isPermaLink="true">https://non-traditional.dev/getting-a-computer-science-degree-in-2022</guid><category><![CDATA[Computer Science]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Sun, 02 Jan 2022 06:43:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/eMP4sYPJ9x0/upload/v1641095583958/WyhEjLWBm.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I don't have a CS degree. In fact, I have a degree in Business Administration. Not a bad degree, but not something that directly helps me in my day-to-day job as a software engineer. This is perfectly fine. When it comes to job qualifications, coding jobs are very much a "Blue Collar" type job, or in other words, a job that cares more about how you do the day-to-day and less about how you learned it. Degrees can help you get a job, especially your first job, but are not the only path needed.</p>
<p>That said, I've always been curious about what skills and knowledge one gains while getting a degree in Computer Science. I've asked several people if their degree helps them in their day-to-day job, and most say not that much. That said, It is hard to measure how much the things learned in a degree help you learn new skills. There is no doubt that the programing class I took my senior year helped me learn to code more than 20 years later. In that same vein, those who have gotten a degree in Computer Science have an interesting skill that others don't.</p>
<h2 id="heading-im-getting-a-cs-degree-in-2022-kinda">I'm getting a CS degree in 2022, kinda</h2>
<p>Another exciting part of the modern web is that schools like MIT and Harvard provide many online courses for free. It is legit possible to "take" all the required classes for some of the degrees at MIT 100% online for free. I get it that you don't get credit for it, but all the skills and knowledge are there to be learned for free.</p>
<p>So that is what I am going to do in 2022. I will earn my CS degree using MIT Open Course Ware and <a target="_blank" href="http://catalog.mit.edu/degree-charts/computer-science-engineering-course-6-3/">the required course list found at MIT's Department of Electrical Engineering and Computer Science website</a>.</p>
<p>Since I am the one giving myself this "degree," I will go ahead and accept my previous business degree in place of taking any general studies. This means the courses I am going to take are the following, in order:</p>
<ol>
<li>6.0001 - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0001-introduction-to-computer-science-and-programming-in-python-fall-2016/">Introduction to Computer Science Programming in Python</a></li>
<li>6.0002 - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0002-introduction-to-computational-thinking-and-data-science-fall-2016/">Introduction to Computational Thinking and Data Science</a> (replacement for Fundamentals of Programing since it isn't available)</li>
<li>6.004 - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-004-computation-structures-spring-2017">Computation Structures</a></li>
<li>6.006 - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/">Introduction to Algorithms</a></li>
<li>6.02 - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-02-introduction-to-eecs-ii-digital-communication-systems-fall-2012/">Introduction to EECS via Communication Networks</a></li>
<li>6.031 - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-005-elements-of-software-construction-fall-2008/">Elements of Software Construction</a></li>
<li>6.033 - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-033-computer-system-engineering-spring-2018">Computer Systems Engineering</a></li>
<li>6.034 - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-034-artificial-intelligence-fall-2010/">Artificial Intelligence</a></li>
<li>6.042J - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-042j-mathematics-for-computer-science-spring-2015/">Mathematics for Computer Science</a></li>
<li>6.046J - <a target="_blank" href="https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-046j-design-and-analysis-of-algorithms-spring-2015">Design and Analysis of Algorithms</a></li>
</ol>
<p>In addition, I will need to pick two courses from the advanced undergraduate courses, but I will put that off until after I have finished the other courses. I intend to finish all of these courses in 2022 to end the year with my special CS degree.</p>
<p>One final note, I will use TypeScript for all the courses when at all possible, and I will push up all the code to GitHub.  </p>
<p>That's, my goal for 2022 and I hope you follow me as I go through this journey this year.</p>
]]></content:encoded></item><item><title><![CDATA[Modernizing JavaScript Code: The Comparator Function]]></title><description><![CDATA[After three posts on the subject, I decided to officially make this a new series called Modernizing JavaScript Code.. This one will be short and sweet but still helpful as we continue down the path of learning about functional programming.
Comparator...]]></description><link>https://non-traditional.dev/modernizing-javascript-code-the-comparator-function</link><guid isPermaLink="true">https://non-traditional.dev/modernizing-javascript-code-the-comparator-function</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Fri, 10 Dec 2021 16:40:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/-80JPdRkDMA/upload/v1639093074870/uvqR5H_l3.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After three posts on the subject, I decided to officially make this <a target="_blank" href="https://non-traditional.dev/series/modern-js">a new series called Modernizing JavaScript Code.</a>. This one will be short and sweet but still helpful as we continue down the path of learning about functional programming.</p>
<h2 id="heading-comparator-functions-vs-predicate-functions">Comparator Functions vs Predicate Functions</h2>
<p>Before we go into the code, we need to go into some terminology. There are generally two ways to write functions that compare things. There is the intuitive way which is to take your inputs and return <code>true</code> or <code>false</code>, like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkIsLessThan</span>(<span class="hljs-params">x, y</span>) </span>{
  <span class="hljs-keyword">return</span> x &lt; y;
}
</code></pre>
<p>These functions are called <strong>predicates</strong>. Another comparing function will take two values and return a number greater than <code>0</code> if the first value is greater than the second, less than <code>0</code> if it is less than the second, and return <code>0</code> if they are equal. These functions are called <strong>comparators</strong>. It is common to see it used in the <code>Array.sort</code> method:</p>
<pre><code class="lang-javascript">[<span class="hljs-number">5</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">8</span>].sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a - b);
<span class="hljs-comment">// [1, 3, 5, 8]</span>
</code></pre>
<p>The difficulty is that comparators are not always intuitive to write, especially when what you are comparing are not numbers but instead are objects of users. They are also not generally useful outside of those contexts that need them.</p>
<p>In the book, Functional Javascript, we are given a function called <code>comparator</code> that takes a preditcate function and returns an comparator function that does the same logic. Here is that original code example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">comparator</span>(<span class="hljs-params">pred</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">x, y</span>) </span>{
    <span class="hljs-keyword">if</span> (pred(x, y)) <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (pred(y, x)) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
  };
}

[<span class="hljs-number">5</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">8</span>].sort(comparator(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a &lt; b));
<span class="hljs-comment">// [1, 2, 5, 8]</span>

[<span class="hljs-number">5</span>, <span class="hljs-string">"1"</span>, <span class="hljs-string">"2"</span>, <span class="hljs-number">8</span>].sort(comparator(isString));
<span class="hljs-comment">// ["2", "1", 5, 8]</span>
</code></pre>
<p>(Technically, in the book, each of the <code>pred</code> calls are wrapped in a function called <code>truthy</code>, but that function is not really part of this discussion, so I am intentionally leaving that out. I think you can guess what the <code>truthy</code> function does on a high level.)</p>
<p>The above code takes a predicate function, and it will return a function that takes two arguments. It will first pass the arguments to the predicate function in the order it received them. If it returns a <code>true</code>, the function will return <code>-1</code>. Otherwise, it will check the value in the predicate function again, but this time with arguments switched. Once again, if the value is <code>true</code>, the function will return <code>1</code>. If neither function calls return <code>true</code>, it will return <code>0</code>.</p>
<p>So let's modernize it. <a target="_blank" href="https://non-traditional.dev/modernizing-code-splat-and-unsplat-78aa9d0dd77f">In a previous post</a>, I mention that I have two rules of function styles:</p>
<ol>
<li>I prefer the traditional syntax for top-level, named functions.</li>
<li>I prefer the arrow syntax for anonymous functions, with implicit returns if the return is simple</li>
</ol>
<p>The other thing that I prefer, is <a target="_blank" href="https://non-traditional.dev/how-to-make-your-conditional-statements-easier-to-read-in-javascript-6e8c3f5e44f6">to avoid the <code>else</code> statement in my if-blocks.</a> Given those two things, we can refactor our <code>comparator</code> function like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">comparator</span>(<span class="hljs-params">pred</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">x, y</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (pred(x, y)) <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    <span class="hljs-keyword">if</span> (pred(y, x)) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
  };
}

[<span class="hljs-number">5</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">8</span>].sort(comparator(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a &lt; b));
<span class="hljs-comment">// [1, 2, 5, 8]</span>

[<span class="hljs-number">5</span>, <span class="hljs-string">"1"</span>, <span class="hljs-string">"2"</span>, <span class="hljs-number">8</span>].sort(comparator(isString));
<span class="hljs-comment">// ["2", "1", 5, 8]</span>
</code></pre>
<p>Now let's add types. First of all, I think it is worth our time to define a <code>PredicateFunction</code> type and a <code>ComparatorFunction</code> type:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> PredicateFunction = <span class="hljs-function">(<span class="hljs-params">x: unknown, y: unknown</span>) =&gt;</span> <span class="hljs-built_in">boolean</span>;

<span class="hljs-keyword">type</span> ComparatorFunction = <span class="hljs-function">(<span class="hljs-params">x: unknown, y: unknown</span>) =&gt;</span> <span class="hljs-number">1</span> | <span class="hljs-number">-1</span> | <span class="hljs-number">0</span>;
</code></pre>
<p>In the above, we state that both functions take two unknown values and will either return a boolean if it is of a <code>PredicateFunction</code> type or <code>1 | -1 | 0</code> if it is of a <code>ComparatorFunction</code> type. One could argue that a <code>ComparatorFunction</code> type only needs to return a <code>number</code>, but I would prefer to be more specific if that is possible.</p>
<p>So now the only thing we need to do is to add that to our function signature, like this:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">comparator</span>(<span class="hljs-params">pred: PredicateFunction</span>): <span class="hljs-title">ComparatorFunction</span> </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">x, y</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (pred(x, y)) <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    <span class="hljs-keyword">if</span> (pred(y, x)) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
  };
}

[<span class="hljs-number">5</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">8</span>].sort(comparator(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a &lt; b));
<span class="hljs-comment">// [1, 2, 5, 8]</span>

[<span class="hljs-number">5</span>, <span class="hljs-string">"1"</span>, <span class="hljs-string">"2"</span>, <span class="hljs-number">8</span>].sort(comparator(isString));
<span class="hljs-comment">// ["2", "1", 5, 8]</span>
</code></pre>
<p>Luckily, nothing else is needed. All other types can be inferred from these two types added to the function signature. We have a nice type-safe utility function that takes in a predicate function and returns a comparator function.</p>
]]></content:encoded></item><item><title><![CDATA[TypeScript and Best Practices: Modernizing the nth Function in JavaScript]]></title><description><![CDATA[Are you looking to modernize your JavaScript code? Look no further than our posts on updating code examples from books. In this third installment, we’ll show you how to modernize the nth function from "Functional JavaScript." We'll walk you through u...]]></description><link>https://non-traditional.dev/typescript-and-best-practices-modernizing-the-nth-function-in-javascript</link><guid isPermaLink="true">https://non-traditional.dev/typescript-and-best-practices-modernizing-the-nth-function-in-javascript</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Fri, 03 Dec 2021 19:10:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/SsBI9pweAeA/upload/v1638428473224/hvZ-FhpZM5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you looking to modernize your JavaScript code? Look no further than our posts on updating code examples from books. In this third installment, we’ll show you how to modernize the <code>nth</code> function from "Functional JavaScript." We'll walk you through updating the code, including adding types with TypeScript. Follow along and learn how to update your code with the latest best practices.</p>
<p>Here are the original examples:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isIndexed</span>(<span class="hljs-params">data</span>) </span>{
  <span class="hljs-keyword">return</span> _.isArray(data) || _.isString(data);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nth</span>(<span class="hljs-params">a, index</span>) </span>{
  <span class="hljs-keyword">if</span> (!_.isNumber(index)) fail(<span class="hljs-string">"Expected a number as the index"</span>);
  <span class="hljs-keyword">if</span> (!isIndexed(a)) fail(<span class="hljs-string">"Not supported on non-indexed type"</span>);
  <span class="hljs-keyword">if</span> (index &lt; <span class="hljs-number">0</span> || index &gt; a.length - <span class="hljs-number">1</span>) fail(<span class="hljs-string">"Index value is out of bounds"</span>);

  <span class="hljs-keyword">return</span> a[index];
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">second</span>(<span class="hljs-params">a</span>) </span>{
  <span class="hljs-keyword">return</span> nth(a, <span class="hljs-number">1</span>);
}

second(<span class="hljs-string">"abc"</span>); <span class="hljs-comment">// b</span>
nth([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-number">0</span>); <span class="hljs-comment">// 1</span>
nth({}, <span class="hljs-number">2</span>); <span class="hljs-comment">// Error: Not supported on non-indexed type</span>
</code></pre>
<p>The <code>nth</code> function takes in an indexable value and an index. It does some guards to make sure you have actually passed in an indexable value and an index that is in bounds, and if everything is safe, it will return the value at the index. Since we already went over the <code>fail</code> function in <a target="_blank" href="https://non-traditional.dev/modernizing-code-examples-from-books-parseage-a6a4177d5b38">the previous post</a>, I have left that code out.</p>
<p>Let's start with the <code>isIndexed</code> function. This uses two utilities from underscore.js to confirm if the value is either an array or a string. There isn't an "array" type in JavaScript that you can check using the <code>typeof</code> operator. If you call <code>typeof []</code>, you will get "object." This is because arrays are just objects under the hood. In the past, we relied on utility functions, like <code>_.isArray</code> to reliably check if value actually is an array and not just an object.</p>
<p>Luckily, we have a static method on the <code>Array</code> object called <code>isArray</code> that does this without needing a utility library. You can <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray">learn more about <code>Array.isArray</code> over at MDN.</a>. Also, in the last post, we created our own <code>assertIsString</code> function. We can steal that logic and replace both of these checks like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isString</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">return</span> toString.call(value) === <span class="hljs-string">"[object String]"</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isIndexed</span>(<span class="hljs-params">data</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.isArray(data) || isString(data);
}
</code></pre>
<p>As for the <code>nth</code> function, the only thing we have in there that should be updated is the <code>_.isNumber</code> function from underscore. We can adapt our <code>isString</code> function to be an <code>isNumber</code> function with one tweak:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isNumber</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">return</span> toString.call(value) === <span class="hljs-string">"[object Number]"</span>;
}
</code></pre>
<p>So we can update the example to look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isNumber</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">return</span> toString.call(value) === <span class="hljs-string">"[object Number]"</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isString</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">return</span> toString.call(value) === <span class="hljs-string">"[object String]"</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isIndexed</span>(<span class="hljs-params">data</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.isArray(data) || isString(data);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nth</span>(<span class="hljs-params">a, index</span>) </span>{
  <span class="hljs-keyword">if</span> (!isNumber(index)) fail(<span class="hljs-string">"Expected a number as the index"</span>);
  <span class="hljs-keyword">if</span> (!isIndexed(a)) fail(<span class="hljs-string">"Not supported on non-indexed type"</span>);
  <span class="hljs-keyword">if</span> (index &lt; <span class="hljs-number">0</span> || index &gt; a.length - <span class="hljs-number">1</span>) fail(<span class="hljs-string">"Index value is out of bounds"</span>);

  <span class="hljs-keyword">return</span> a[index];
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">second</span>(<span class="hljs-params">a</span>) </span>{
  <span class="hljs-keyword">return</span> nth(a, <span class="hljs-number">1</span>);
}

second(<span class="hljs-string">"abc"</span>); <span class="hljs-comment">// b</span>
nth([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-number">0</span>); <span class="hljs-comment">// 1</span>
nth({}, <span class="hljs-number">2</span>); <span class="hljs-comment">// Error: Not supported on non-indexed type</span>
</code></pre>
<p>Now, let's add types. Our <code>is</code> functions are simple enough. Each one takes an unknown value and determines if it is something, so let's type them like this:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isNumber</span>(<span class="hljs-params">value: unknown</span>) </span>{
  <span class="hljs-keyword">return</span> toString.call(value) === <span class="hljs-string">"[object Number]"</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isString</span>(<span class="hljs-params">value: unknown</span>) </span>{
  <span class="hljs-keyword">return</span> toString.call(value) === <span class="hljs-string">"[object String]"</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isIndexed</span>(<span class="hljs-params">data: unknown</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.isArray(data) || isString(data);
}
</code></pre>
<p>Now let's add the types to our <code>nth</code> function. In the previous post, I typed the function as unknown, partially because I wanted to keep the spirit of how the function was written but partially so we could learn more about assertion functions. In a real TypeScript code base, we would write the types much more explicitly.</p>
<p>Our <code>nth</code> function takes two arguments: <code>a</code> and <code>index</code>. <code>index</code> is simple enough to type because it needs to be of type <code>number</code>. <code>a</code> could either be a string or an array. So first, let's create a type called <code>Indexed</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> Indexed = <span class="hljs-built_in">Array</span>&lt;unknown&gt; | <span class="hljs-built_in">string</span>;
</code></pre>
<p>This essentially says that <code>Indexed</code> could be an array of unknown values or a string. Now we could do something like this:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nth</span>(<span class="hljs-params">a: Indexed, index: <span class="hljs-built_in">number</span></span>) </span>{}
</code></pre>
<p>But this will force the value of <code>a</code> to be an array of unknown values if we pass in an array. Let TypeScript infer what type of array we are passing in would be much nicer. Luckily we can do that using generics. Let's look at the updated types:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nth</span>&lt;<span class="hljs-title">T</span> <span class="hljs-title">extends</span> <span class="hljs-title">Indexed</span>&gt;(<span class="hljs-params">a: T, index: <span class="hljs-built_in">number</span></span>): <span class="hljs-title">T</span>[<span class="hljs-title">number</span>] </span>{}
</code></pre>
<p>Let's break that down. First, we are saying that <code>nth</code> takes a generic value of <code>T</code> that must extend the <code>Indexed</code> type we declared. Then we say that <code>a</code> is of type <code>T</code> and that we are returning <code>T[number]</code> or the value at the index of <code>T</code>.</p>
<p>By having <code>T</code> extend <code>Indexed</code>, we are now letting Typescript infer the array's values to know the return type accurately. For example, if we call <code>nth([1,2,3], 0)</code>, Typescript will know that the return type is of a type number.</p>
<p>The <code>second</code> function below can be typed the same way, except it wont need an explicit return type since it can infer that from the <code>nth</code> function we are calling. So now let's update the entire example using TypesScript:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isNumber</span>(<span class="hljs-params">value: unknown</span>) </span>{
  <span class="hljs-keyword">return</span> toString.call(value) === <span class="hljs-string">"[object Number]"</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isString</span>(<span class="hljs-params">value: unknown</span>) </span>{
  <span class="hljs-keyword">return</span> toString.call(value) === <span class="hljs-string">"[object String]"</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isIndexed</span>(<span class="hljs-params">data: unknown</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.isArray(data) || isString(data);
}

<span class="hljs-keyword">type</span> Indexed = <span class="hljs-built_in">Array</span>&lt;unknown&gt; | <span class="hljs-built_in">string</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nth</span>&lt;<span class="hljs-title">T</span> <span class="hljs-title">extends</span> <span class="hljs-title">Indexed</span>&gt;(<span class="hljs-params">a: T, index: <span class="hljs-built_in">number</span></span>): <span class="hljs-title">T</span>[<span class="hljs-title">number</span>] </span>{
  <span class="hljs-keyword">if</span> (!isNumber(index)) fail(<span class="hljs-string">"Expected a number as the index"</span>);
  <span class="hljs-keyword">if</span> (!isIndexed(a)) fail(<span class="hljs-string">"Not supported on non-indexed type"</span>);
  <span class="hljs-keyword">if</span> (index &lt; <span class="hljs-number">0</span> || index &gt; a.length - <span class="hljs-number">1</span>) fail(<span class="hljs-string">"Index value is out of bounds"</span>);

  <span class="hljs-keyword">return</span> a[index];
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">second</span>&lt;<span class="hljs-title">T</span> <span class="hljs-title">extends</span> <span class="hljs-title">Indexed</span>&gt;(<span class="hljs-params">a: T</span>) </span>{
  <span class="hljs-keyword">return</span> nth(a, <span class="hljs-number">1</span>);
}

second(<span class="hljs-string">"abc"</span>); <span class="hljs-comment">// b</span>
nth([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], <span class="hljs-number">0</span>); <span class="hljs-comment">// 1</span>
nth({}, <span class="hljs-number">2</span>); <span class="hljs-comment">// TypeError</span>
</code></pre>
<p>There you have it, a fully modernized and typed example from the classic "Functional JavaScript." I highly recommend checking it out, and I'll see you next time.</p>
]]></content:encoded></item><item><title><![CDATA[Create CSS-Only Components with a Prop-Like API Using the AVO Method]]></title><description><![CDATA[Are you looking for a fast and efficient way to create layouts for your React apps? Look no further than bedrock-layout. dev, a layout library built originally for React. But what if you need to write CSS-only components without React? Enter the AVO ...]]></description><link>https://non-traditional.dev/create-css-only-components-with-a-prop-like-api-using-the-avo-method</link><guid isPermaLink="true">https://non-traditional.dev/create-css-only-components-with-a-prop-like-api-using-the-avo-method</guid><category><![CDATA[CSS]]></category><category><![CDATA[CSS Frameworks]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[layout]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Thu, 02 Dec 2021 02:39:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/XGNPO89fqV0/upload/v1638331316080/jRWmqkSTl9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you looking for a fast and efficient way to create layouts for your React apps? Look no further than <a target="_blank" href="https://bedrock-layout.dev">bedrock-layout. dev</a>, a layout library built originally for React. But what if you need to write CSS-only components without React? Enter the AVO method, a BEM dialect that uses data attributes instead of class names to create a prop-like API for your CSS. In this article, we'll show you how to use the AVO method to translate React-based components to CSS-based components and provide some good patterns to follow.</p>
<h2 id="heading-introducing-the-avo-method">Introducing the AVO method</h2>
<p>Luckily, I was introduced to a different way of writing my CSS called the AVO method. The AVO method, which stands for Attribute Values-Objects, is a BEM dialect created by Michael Chan that uses data attributes instead of class names. This is unique in that I can point my selectors to the data attribute and use the value assigned to the data attribute.</p>
<p>A tradional class name approach would have yielded something like this:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"split hero split-fraction-1/4 center-text"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"--gutter:1rem"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- Hero content here--&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
</code></pre>
<p>The above example can be rewritten like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">header</span>
  <span class="hljs-attr">data-bedrock-split</span>=<span class="hljs-string">"fraction:1/4"</span>
  <span class="hljs-attr">style</span>=<span class="hljs-string">"--gutter:1rem"</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"hero center-text"</span>
&gt;</span>
  <span class="hljs-comment">&lt;!-- Hero content here--&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>
</code></pre>
<p>At first glance, not much has changed, but you will notice some fantastic benefits immediately after further inspection. First, using a data attribute forces you to keep the styling of the data attribute together, unlike the class-based methodologies that can’t stop you from putting your classes in any order you want. Even more important is that you get that prop-like API we love in our front-end frameworks.</p>
<p>There is no way I can do it justice in this short post, so I highly recommend you check out Michael's fantastic content on the subject:</p>
<p><a target="_blank" href="https://chan.dev/posts/avo-a-bem-dialect-using-data-attributes/">https://chan.dev/posts/avo-a-bem-dialect-using-data-attributes/</a></p>
<p>For the rest of the post, I want to show some good patterns I found when converting my React-based components to CSS-based components.</p>
<h2 id="heading-how-to-translate-boolean-props-and-props-with-a-fixed-number-of-values">How to translate boolean props and props with a fixed number of values</h2>
<p>Boolean props are very easy to implement. Much like how you do boolean props in React, you can select based on the existence of the string.</p>
<p>For example, The <a target="_blank" href="https://bedrock-layout.dev/?path=/docs/components-center--api"><code>Center</code> component</a> has two boolean props: <code>centerText</code> and <code>centerChildren</code>. To convert this to AVO, one needs to select based if that string exists, like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-attr">[data-bedrock-center~=<span class="hljs-string">"center-children"</span>]</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">align-items</span>: center;
}

<span class="hljs-selector-attr">[data-bedrock-center~=<span class="hljs-string">"center-text"</span>]</span> {
  <span class="hljs-attribute">text-align</span>: center;
}
</code></pre>
<p>Then we can apply it like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-bedrock-center</span>=<span class="hljs-string">"center-text"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- text alignment will be centered --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-bedrock-center</span>=<span class="hljs-string">"center-children"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- children will be centered --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-bedrock-center</span>=<span class="hljs-string">"center-text center-children"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- text alignment and children will be centered --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>You will notice in the above example that we are using <code>~=</code>. If we only use <code>=</code>, the string must be an exact match. However, <code>~=</code> lets us look for any of the space-delimited words to find a match.</p>
<p>Note this will not match on partial words. If I used the string <code>center-children-vertically</code>, this would not match. There is a way to do this kind of math, but I only recommend it for a particular scenario, which I will review later.</p>
<p>This strategy also works well if your prop's values are enumerable; in other words, there is a fixed amount of acceptable values. Here I would use a naming pattern where you provide both the prop name and value delimited by a semi-colon: <code>&lt;prop-name&gt;:&lt;value&gt;</code>.</p>
<p>For example, <a target="_blank" href="https://bedrock-layout.dev/?path=/docs/components-split--api">the <code>Split</code> component</a> has a fixed set of values for it's <code>fraction</code> prop: <code>1/4</code>, <code>1/3</code>, <code>1/2</code>, <code>2/3</code>, <code>3/4</code>, <code>auto-start</code>, and <code>auto-end</code>. This would translate to <code>fraction:1/4</code>, <code>fraction:1/3</code>, and so on.</p>
<p>With this in mind, we can write our CSS like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-attr">[data-bedrock-split~=<span class="hljs-string">"fraction:1/4"</span>]</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">3</span>fr;
}

<span class="hljs-selector-attr">[data-bedrock-split~=<span class="hljs-string">"fraction:1/3"</span>]</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">2</span>fr;
}

<span class="hljs-selector-attr">[data-bedrock-split~=<span class="hljs-string">"fraction:1/2"</span>]</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr;
}

<span class="hljs-selector-attr">[data-bedrock-split~=<span class="hljs-string">"fraction:2/3"</span>]</span> {
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">2</span>fr <span class="hljs-number">1</span>fr;
}

<span class="hljs-comment">/* ect */</span>
</code></pre>
<p>and we can use that in our HTML, like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-bedrock-split</span>=<span class="hljs-string">"fraction:1/4"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-bedrock-split</span>=<span class="hljs-string">"fraction:1/3"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-bedrock-split</span>=<span class="hljs-string">"fraction:1/2"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-bedrock-split</span>=<span class="hljs-string">"fraction:2/3"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<h2 id="heading-how-to-translate-props-with-unknown-values">How to translate props with unknown values</h2>
<p>Sometimes props rely on the user to provide a value, and there is no way to control those values ahead of time. In those scenarios, you may want to reach for a custom property. CSS custom properties, also known as CSS variables, let you define your own properties and values, which you can use in your CSS. Often we see these values being declared in the <code>root</code>, like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-pseudo">:root</span> {
  <span class="hljs-attribute">--my-custom-size</span>: <span class="hljs-number">15px</span>;
  <span class="hljs-attribute">--my-custom-color</span>: dodgerblue;
}
</code></pre>
<p>The thing is that nothing says can't be declared inline like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"--my-custom-size: 15px; --my-custom-color: dodgerblue;"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>This allows us to use them in a very "prop" like way. For example, The <a target="_blank" href="https://bedrock-layout.dev/?path=/docs/components-center--api"><code>Center</code> component</a> has a prop called <code>maxWidth</code> that accepts any CSS length or percentage. We can translate that into a CSS custom property like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-attr">[data-bedrock-center]</span> {
  <span class="hljs-attribute">max-inline-size</span>: <span class="hljs-built_in">var</span>(--maxWidth, <span class="hljs-number">100%</span>);
}
</code></pre>
<p>and we can then use that in our HTML like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-bedrock-center</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"--maxWidth: 75%"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    Nulla luctus nisl nec dui auctor volutpat. Phasellus condimentum elementum
    enim in pharetra.
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Some of you might be saying, wait, inline styles are bad, aren’t they? And the answer to that is: no, they are not bad. CSS follows an exception-based styling where you start with the most general styles and then work down to the most specific styles. Inline styles are meant to be the most specific parts of your styles, the ultimate exception. If you used them for all your styling, it would be bad, but these are being used to make one specific change to a specific element on the page, so no, they are not bad to use in this case.</p>
<h2 id="heading-styling-based-on-the-existence-of-a-prop">Styling based on the existence of a prop</h2>
<p>Sometimes you only want to add styles if a prop exists and is not based on its value. For example, the user can use the <a target="_blank" href="https://bedrock-layout.dev/?path=/docs/components-inline--api"><code>Inline</code> component</a> to pass in a CSS length to a <code>switchAt</code> prop to define the threshold that the component will switch to a stacking layout. If the threshold isn't provided, I don't even want certain styles applied.</p>
<p>To achieve this in the AVO method, we need to change our selector slightly. Instead of using <code>~=</code>, we will use <code>*=</code> instead. This will let us search for the existence of a string, no matter if it's part of a larger string. So we can write our AVO style of the <code>switchAt</code> prop like this:</p>
<pre><code class="lang-css"><span class="hljs-selector-attr">[data-bedrock-inline]</span><span class="hljs-selector-attr">[style*=<span class="hljs-string">"--switchAt"</span>]</span> {
  <span class="hljs-attribute">flex-wrap</span>: wrap;
}
<span class="hljs-selector-attr">[data-bedrock-inline]</span><span class="hljs-selector-attr">[style*=<span class="hljs-string">"--switchAt"</span>]</span> &gt; * {
  <span class="hljs-attribute">min-inline-size</span>: fit-content;
  <span class="hljs-attribute">flex-basis</span>: <span class="hljs-built_in">calc</span>((var(--switchAt) - (<span class="hljs-number">100%</span> - <span class="hljs-built_in">var</span>(--gutter))) * <span class="hljs-number">999</span>);
}
</code></pre>
<p>The above code is looking for the existence of the <code>--switchAt</code> custom property being passed inline to the <code>style</code> attribute. If it does, it will apply styles to both the parent and all the children. Otherwise, these styles will not be applied. So now we can write that in HTML like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">data-bedrock-inline</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"--switchAt: 45rem"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>In conclusion, the AVO method is a powerful and flexible way to write CSS that can help you create CSS-only components with a prop-like API. By using data attributes instead of class names, you can keep your styling organized and easy to maintain. We've shown you some good patterns to follow when translating React-based components to CSS-based components, including how to handle boolean props, props with a fixed number of values, and props with unknown values. We hope this article has been helpful and that you'll consider using the AVO method in your next project. Don't forget to check out the <a target="_blank" href="https://github.com/Bedrock-Layouts/Bedrock/tree/main/packages/bedrock-layout-css/src/components">Bedrock Layout CSS version on Github</a> and <a target="_blank" href="https://chan.dev/posts/avo-a-bem-dialect-using-data-attributes/#attribute">Michael Chan's content on the subject for more information.</a></p>
]]></content:encoded></item><item><title><![CDATA[Fetching Data In React]]></title><description><![CDATA[Photo by Anthony Duran on Unsplash
The React Docs are great and getting better, but I have always felt it lacked a basic explanation of how to fetch data. So much is devoted to state and props; we don’t get into where that state and props come from.
...]]></description><link>https://non-traditional.dev/fetching-data-in-react-b2ddfa12ccce</link><guid isPermaLink="true">https://non-traditional.dev/fetching-data-in-react-b2ddfa12ccce</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[React]]></category><category><![CDATA[ReactHooks]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Tue, 30 Nov 2021 14:36:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638316804082/eI9vi1mvQ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@fightmorefilms?utm_source=medium&amp;utm_medium=referral">Anthony Duran</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>The React Docs are great and getting better, but I have always felt it lacked a basic explanation of how to fetch data. So much is devoted to state and props; we don’t get into where that state and props come from.</p>
<p>Some great libraries, like React-Query, help fetch data in a React app, but, unfortunately, we don’t at least have some basic concept of data fetching before we bring in a 3rd party library that we may or may not need.</p>
<p>For this reason, I thought I would quickly go over some basics regarding data fetching and some opinions that I like to follow.</p>
<h3 id="heading-the-basics">The Basics</h3>
<p>There are two essential parts to data fetching: We need to trigger an action to get the data, and we need to store that data somewhere. This means we need to use <code>useEffect</code> and <code>useState</code> to handle those two-part. This is what that looks like:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> UserCard = <span class="hljs-function">() =&gt;</span>{  
  <span class="hljs-keyword">const</span> [user, setUser] = useState()  

  useEffect(<span class="hljs-function">()=&gt;</span>{   
    fetch(<span class="hljs-string">'/api/user/travis'</span>)  
     .then(<span class="hljs-function"><span class="hljs-params">res</span>=&gt;</span>res.ok ? res.json() : <span class="hljs-built_in">Promise</span>.reject(res))  
     .then(setUser)  
  })  

  <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* render card here */</span>)   

}
</code></pre>
<p>In the above component, we have state that is updated when we get a user back from our API. That is the bare minimum we need when fetching data in a React app. Now chances are we want our Card to be a bit more dynamic, so lets, quickly update it to take any user:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> UserCard = <span class="hljs-function">(<span class="hljs-params">{ userName }</span>) =&gt;</span>{  
  <span class="hljs-keyword">const</span> [user, setUser] = useState()  

  useEffect(<span class="hljs-function">()=&gt;</span>{   
    fetch(<span class="hljs-string">`/api/user/<span class="hljs-subst">${userName}</span>`</span>)  
     .then(<span class="hljs-function"><span class="hljs-params">res</span>=&gt;</span>res.ok ? res.json() : <span class="hljs-built_in">Promise</span>.reject(res))  
     .then(setUser)  
  },[userName])  

  <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* render card here */</span>)   

}
</code></pre>
<p>With this update, we will get the user data of whichever <code>userName</code> is passed in. If the <code>userName</code> prop changes, we will fetch new data and set it to state when it returns.</p>
<p>This might not seem like much, but this is all you need to know to start fetching data in a React Component. However, I think it would be helpful to share my opinions on some of my personal best practices.</p>
<h3 id="heading-move-the-fetching-into-its-own-function">Move the ‘fetching’ into its own function</h3>
<p>The “how” we get our data is not crucial to our React Component. All it cares about is that it requests the data and what to do when it comes back. There is also much more you need to do with the returned data than what my examples show. One typically gets more data back than you need. Also, sometimes the data you need requires multiple API calls. API’s also change, and maintaining that across your app can get complicated if each React component knows too much about how the data is fetched.</p>
<p>For this reason, I prefer to move the implementation of the fetching into its own function, typically in an <code>api</code> folder for organization purposes:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUserData</span>(<span class="hljs-params">userName</span>)</span>{  
   <span class="hljs-keyword">return</span> fetch(<span class="hljs-string">`/api/user/<span class="hljs-subst">${userName}</span>`</span>)  
     .then(<span class="hljs-function"><span class="hljs-params">res</span>=&gt;</span> res.ok ? res.json() : <span class="hljs-built_in">Promise</span>.reject(res))  
     .then(<span class="hljs-function">(<span class="hljs-params">{fullName, images, bio}</span>)=&gt;</span>({  
       <span class="hljs-attr">name</span>:fullName,  
       <span class="hljs-attr">avatar</span>:images.large,  
       bio,   
     }))  
}
</code></pre>
<p>Now our UserCard can be updated like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> UserCard = <span class="hljs-function">(<span class="hljs-params">{ userName }</span>) =&gt;</span>{  
  <span class="hljs-keyword">const</span> [user, setUser] = useState()  

  useEffect(<span class="hljs-function">()=&gt;</span>{   
    getUserData(userName)  
     .then(setUser)  
  },[userName])  

  <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* render card here */</span>)   

}
</code></pre>
<p>This is much easier to reason about in our Component and is more resilient if we change our back-end API.</p>
<h3 id="heading-handle-all-the-states">Handle all the states</h3>
<p>Fetching data is not as simple as getting data and showing it. When you are fetching data, you are always in one of three states. You are either loading data, have the data, or there was an error fetching the data.</p>
<p>So it would be best if you handled all those states in your component, for example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> UserCard = <span class="hljs-function">(<span class="hljs-params">{ userName }</span>) =&gt;</span>{  
  <span class="hljs-keyword">const</span> [user, setUser] = useState()  
  <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">true</span>)  
  <span class="hljs-keyword">const</span> [error, setError] = useState()  

  useEffect(<span class="hljs-function">()=&gt;</span>{   
    setLoading(<span class="hljs-literal">true</span>)  
    setError()  

    getUserData(userName)  
     .then(setUser)  
     .catch(setError)  
     .finally(<span class="hljs-function">()=&gt;</span>setLoading(<span class="hljs-literal">false</span>))  

  },[userName])

  <span class="hljs-keyword">if</span>(error){  
   <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* error state */</span>)  
  }

  <span class="hljs-keyword">if</span>(loading){  
   <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* loading state */</span>)  
  }

  <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* render card here */</span>)   

}
</code></pre>
<p>In our <code>useEffect</code> we start by initializing our loading and error states. We do this so that we will set our states back to their initial states and then fetch the data if the prop changes. On top of that, we added a <code>catch</code> and <code>finally</code> to our promise chain. If there is an error, we will catch that and set the error state. We use <code>finally</code> so that we will set the loading state to false no matter if we have an error.</p>
<p>There is also another state that we often forget about. This is what do we do if the component unmounts before our data gets back? We will have an error if we try to update any of our states after the component has unmounted. Also, what do we do if we change the prop multiple times and send off multiple requests? How do we know if we are updating the state with the correct user since we have no control over which data will return in which order? Luckily we can refactor our code to handle both of these circumstances.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> UserCard = <span class="hljs-function">(<span class="hljs-params">{ userName }</span>) =&gt;</span>{  
  <span class="hljs-keyword">const</span> [fetchState, setFetchState] = useState({ <span class="hljs-attr">loading</span>:<span class="hljs-literal">true</span> })

  <span class="hljs-keyword">const</span> {user, error, loading} = fetchState  

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

    setFetchState({ <span class="hljs-attr">loading</span>: <span class="hljs-literal">true</span> })  

    getUserData(userName)  
     .then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> ({ user }))  
     .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> ({ error }))  
     .then(<span class="hljs-function"><span class="hljs-params">state</span>=&gt;</span>{  
      <span class="hljs-keyword">if</span> (shouldSet) setFetchState({...state, <span class="hljs-attr">loading</span>:<span class="hljs-literal">false</span>})  
     })

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {  
      shouldSet = <span class="hljs-literal">false</span>  
    }  

  },[userName])

  <span class="hljs-keyword">if</span>(error){  
   <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* error state */</span>)  
  }

  <span class="hljs-keyword">if</span>(loading){  
   <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* loading state */</span>)  
  }

  <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* render card here */</span>)   

}
</code></pre>
<p>In this refactoring, we are merging all three states into a single state object. This doesn’t just make things more convenient for us later on, but it also makes sense. Any time we are calling multiple setState functions, chances are we should be grouping those together. These states don’t work in isolation but are part of one state and should be updated together.</p>
<p>Next in our <code>useEffect</code>, we are initializing a <code>shouldSet</code> variable to true. Then we instead of setting the state in our <code>.then</code> or <code>.catch</code> we are returning a partial state with either the user or the error. In our final <code>.then</code> we then verify if the <code>shouldSet</code> variable is still true. If it is, we update the state with our partial state and set loading to false.</p>
<p>This makes this work because we are now returning a cleanup function that will change the value of <code>shouldUpdate</code> to false. This will be set to false if the component unmounts or if the <code>userName</code> changes and the effect is rerun. Either way, we won't update the wrong data or update at all if we don’t want to.</p>
<h3 id="heading-you-probably-want-to-make-a-custom-hook">You probably want to make a custom hook</h3>
<p>Once again, all this logic is starting to make our card cluttered. Also, the <code>UserCard</code> component doesn’t care how we get the states we do, only with what the states are. So it makes sense to refactor this out into a custom hook:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useCardState</span>(<span class="hljs-params">userName</span>)</span>{  
  <span class="hljs-keyword">const</span> [fetchState, setFetchState] = useState({ <span class="hljs-attr">loading</span>:<span class="hljs-literal">true</span> })

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

    setFetchState({ <span class="hljs-attr">loading</span>: <span class="hljs-literal">true</span> })  

    getUserData(userName)  
     .then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> ({ user }))  
     .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> ({ error }))  
     .then(<span class="hljs-function"><span class="hljs-params">state</span>=&gt;</span>{  
      <span class="hljs-keyword">if</span> (shouldSet) setFetchState({...state, <span class="hljs-attr">loading</span>:<span class="hljs-literal">false</span>})  
     })

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {  
      shouldSet = <span class="hljs-literal">false</span>  
    }   
  }, [userName])

 <span class="hljs-keyword">return</span> fetchState  
}
</code></pre>
<p>We have moved all that logic state into a single hook that takes a <code>userName</code> and returns a the <code>fetchState.</code> Now we can use that in our component like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> UserCard = <span class="hljs-function">(<span class="hljs-params">{ userName }</span>) =&gt;</span> {

  <span class="hljs-keyword">const</span> {user, error, loading} = useCardState(userName)

  <span class="hljs-keyword">if</span>(error){  
    <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* error state */</span>)  
  }

  <span class="hljs-keyword">if</span>(loading){  
    <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* loading state */</span>)  
  }

  <span class="hljs-keyword">return</span> (<span class="hljs-comment">/* render card here */</span>)   

}
</code></pre>
<p>Now the <code>UserCard</code> is easier to reason about again, and we can compartmentalize how we fetch that data and what to do while we fetched our data. It’s important to point out that this hook doesn’t need to be in another file and or made “reusable” at this point. As you go, if you find a common pattern that solves a problem, then go ahead and abstract it generally.</p>
<p>These are the basics of how to do data fetching in React and some good strategies to solve common problems associated with it. Hopefully, this helps fill the gap in your React apps.</p>
]]></content:encoded></item><item><title><![CDATA[Converting Object Oriented Code to Functional in JavaScript]]></title><description><![CDATA[Photo by Linus Nylund on Unsplash
JavaScript is an interesting language. It doesn't fit nicely in any one Paradigm. JavaScript does have characteristics of Object-Oriented languages, but it also has attributes of Functional programming languages and ...]]></description><link>https://non-traditional.dev/converting-object-oriented-code-to-functional-in-javascript-f3d50cd06d93</link><guid isPermaLink="true">https://non-traditional.dev/converting-object-oriented-code-to-functional-in-javascript-f3d50cd06d93</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[data structures]]></category><category><![CDATA[Object Oriented Programming]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Mon, 29 Nov 2021 19:55:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638316794769/w-MYhKrH_r.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@dreamsoftheoceans?utm_source=medium&amp;utm_medium=referral">Linus Nylund</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>JavaScript is an interesting language. It doesn't fit nicely in any one Paradigm. JavaScript does have characteristics of Object-Oriented languages, but it also has attributes of Functional programming languages and doesn't strictly follow either style perfectly.</p>
<p>Recently I was looking at some primary computer science material and was reading about data structures, specifically, <a target="_blank" href="https://medium.com/basecs/stacks-and-overflows-dbcf7854dc67">the "Stack" data structure</a>. I noticed that all the examples tend to be object-oriented, and I wondered why other language paradigms were not shown.</p>
<p>That was when I decided to think about what a Stack would look like using other programming paradigms. So that is what we will try to do in this post.</p>
<p>(To keep the code universally readable to all readers here, I am only using JavaScript and not Typescript)</p>
<p>First, let's look at how I would implement a Stack using pure OO.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Stack</span> </span>{
  #head;
  push(value) {
    <span class="hljs-keyword">const</span> node = {
      value,
      <span class="hljs-attr">next</span>: <span class="hljs-built_in">this</span>.#head,
    };
    <span class="hljs-built_in">this</span>.#head = node;
  }
  peak() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.#head?.value;
  }
  pop() {
    <span class="hljs-keyword">const</span> safeNode = <span class="hljs-built_in">this</span>.#head ?? {};
    <span class="hljs-keyword">const</span> poppedValue = safeNode.value;
    <span class="hljs-built_in">this</span>.#head = safeNode.next;
    <span class="hljs-keyword">return</span> poppedValue;
  }
  [<span class="hljs-built_in">Symbol</span>.iterator] = <span class="hljs-function"><span class="hljs-keyword">function</span>* (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> safeNode = <span class="hljs-built_in">this</span>.#head ?? {};
    <span class="hljs-keyword">while</span> (safeNode.value) {
      <span class="hljs-keyword">yield</span> safeNode.value;
      safeNode = safeNode.next ?? {};
    }
  };
}

<span class="hljs-keyword">const</span> stack = <span class="hljs-keyword">new</span> Stack();
stack.push(<span class="hljs-number">1</span>);
stack.push(<span class="hljs-number">2</span>);
stack.peak(); <span class="hljs-comment">// 2</span>
stack.pop(); <span class="hljs-comment">// 2</span>
stack.peak(); <span class="hljs-comment">// 1</span>
stack.push(<span class="hljs-number">3</span>);
stack.push(<span class="hljs-number">4</span>);
stack.push(<span class="hljs-number">2</span>);
stack.push(<span class="hljs-number">2</span>);
<span class="hljs-built_in">console</span>.log([...stack]); <span class="hljs-comment">// [ 2, 2, 4, 3, 1 ]In the above code, we are defining a Stack class that has a private property called #head and three methods called push , pop , and peak that allows you to add an item to the stack, take an item off, and look at the top item on the stack.</span>
</code></pre>
<p>Our <code>Stack</code> is implemented using a linked list. If you are unfamiliar with linked lists, I recommend <a target="_blank" href="https://medium.com/basecs/whats-a-linked-list-anyway-part-1-d8b7e6508b9d">checking out the basecs article on linked lists</a> but summarizing: A linked list is a list of objects called nodes. Each node has two properties: a value and a reference to the next node. To traverse a linked list, you start at the first node, called the head, and keep going to the next node until you run out of nodes.</p>
<p>Our Stack keeps track of the head node in the private <code>#head</code> property. When we call <code>peak</code> it returns the value at the head node. When we call <code>push</code>, it will create a new node with the value provided, assign the node at the <code>#head</code> property to <code>next</code> and assign that new node to the<code>#head</code> property. Finally, when we call <code>pop</code>, we pull the value off the<code>#head</code> property, and then assign the value of <code>next</code> to the<code>#head</code> property.</p>
<p>We are also making our <code>Stack</code> iterable by assigning a generator function to the<code>[Symbol.iterator]</code> property. <a target="_blank" href="https://non-traditional.dev/how-to-code-the-fizz-buzz-challenge-using-javascript-generators-ed7f9f9c18af">You can learn more about generator functions in my blog post on them</a>, but simply put, this allows JavaScript to iterate over the items in the stack, and we can do things like spreading them into an array or using them in a <code>for...of</code> loop.</p>
<p>To use the stack, we call <code>new Stack()</code> and assign that to a variable. From there, we can do all the fun things to a stack you can. This is probably the most common way you will see a <code>Stack</code> implemented.</p>
<p>The first step to making this more functional is to stop mutating our <code>Stack</code> every time we call either the <code>push</code> or <code>pop</code> method. So let's make a new version called <code>ImmutableStack</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImmutableStack</span> </span>{
  #head;

  <span class="hljs-keyword">constructor</span>(node) {
    <span class="hljs-built_in">this</span>.#head = node;
  }

  push(value) {
    <span class="hljs-keyword">const</span> node = {
      value,
      <span class="hljs-attr">next</span>: <span class="hljs-built_in">this</span>.#head,
    };

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ImmutableStack(node);
  }

  peak() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.#head?.value;
  }

  pop() {
    <span class="hljs-keyword">const</span> safeNode = <span class="hljs-built_in">this</span>.#head ?? {};

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ImmutableStack(safeNode.next);
  }

  [<span class="hljs-built_in">Symbol</span>.iterator] = <span class="hljs-function"><span class="hljs-keyword">function</span>* (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> safeNode = <span class="hljs-built_in">this</span>.#head ?? {};
    <span class="hljs-keyword">while</span> (safeNode.value) {
      <span class="hljs-keyword">yield</span> safeNode.value;
      safeNode = safeNode.next ?? {};
    }
  };
}

<span class="hljs-keyword">let</span> stack = <span class="hljs-keyword">new</span> ImmutableStack();

stack = stack.push(<span class="hljs-number">1</span>);
stack = stack.push(<span class="hljs-number">2</span>);
stack.peak(); <span class="hljs-comment">// 2</span>
stack = stack.pop();
stack.peak(); <span class="hljs-comment">// 1</span>

stack = stack.push(<span class="hljs-number">3</span>);
stack = stack.push(<span class="hljs-number">4</span>);
stack = stack.push(<span class="hljs-number">2</span>);
stack = stack.push(<span class="hljs-number">2</span>);

<span class="hljs-built_in">console</span>.log([...stack]); <span class="hljs-comment">// [ 2, 2, 4, 3, 1 ]</span>
</code></pre>
<p>Let's talk about what we changed. We still have a private <code>#head</code> property. Also, our <code>peak</code> and iterator or also still the same. What we changed was that we added a <code>constructor</code> to our class. The <code>constructor</code> allows us to initialize values in our <code>Stack</code> when we call <code>new Stack()</code> in our code. Our constructor lets us optionally pass in a node and assign it to the<code>#head</code> property. This will allow us to initialize our <code>Stack</code> with an existing linked list if we want.</p>
<p>In our <code>push</code> method, we still take in a value, assign it to a new node, and assign the value at the <code>#head</code> property to the <code>next</code> property of that new node. However, instead of changing the value of the <code>#head</code> property, we are returning a new <code>Stack</code> initialized with the new node. The same thing happens in our <code>pop</code> method. We are returning a new <code>Stack</code> initialized with the next node of our stack.</p>
<p>I think it is essential to stop and reiterate why this is helpful. If two parts of our code were looking at that same <code>Stack</code> and one part called <code>push</code> or <code>pop</code> on it. The other part of our code would not know that the value was changed on it. This can lead to unpredictable behavior. Making our Stack immutable ensures that we can write our code and be confident that some other part of our code won't change its values underneath us.</p>
<p>The next evolution into a more functional style is to move away from creating classes at all and instead define methods that take inputs and return values:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> stackUtils = {
  push(head, value) {
    <span class="hljs-keyword">const</span> node = {
      value,
      <span class="hljs-attr">next</span>: head,
    };

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

  peak(head) {
    <span class="hljs-keyword">return</span> head?.value;
  },

  pop(head) {
    <span class="hljs-keyword">const</span> safeNode = head ?? {};

    <span class="hljs-keyword">return</span> safeNode.next;
  },

  getIterator(head) {
    <span class="hljs-keyword">return</span> (<span class="hljs-function"><span class="hljs-keyword">function</span>* (<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">let</span> safeNode = head ?? {};
      <span class="hljs-keyword">while</span> (safeNode.value) {
        <span class="hljs-keyword">yield</span> safeNode.value;
        safeNode = safeNode.next ?? {};
      }
    })();
  },
};

<span class="hljs-keyword">let</span> stack;

stack = stackUtils.push(stack, <span class="hljs-number">1</span>);
stack = stackUtils.push(stack, <span class="hljs-number">2</span>);
stackUtils.peak(stack); <span class="hljs-comment">// 2</span>
stack = stackUtils.pop(stack);
stackUtils.peak(stack); <span class="hljs-comment">// 1</span>

stack = stackUtils.push(stack, <span class="hljs-number">3</span>);
stack = stackUtils.push(stack, <span class="hljs-number">4</span>);
stack = stackUtils.push(stack, <span class="hljs-number">2</span>);
stack = stackUtils.push(stack, <span class="hljs-number">2</span>);

<span class="hljs-built_in">console</span>.log([...stackUtils.getIterator(stack)]); <span class="hljs-comment">// [ 2,2,4,3,1 ]</span>
</code></pre>
<p>In the above code, instead of creating a class, we define an object with utility methods that know how to peak, push, and pop values on a linked list. Since our methods no longer have access to a head property, that value must be passed in as an argument to our methods. For that same reason, we also have created a function <code>getIterator</code> that will generate an iterator for us to use in those circumstances.</p>
<p>Other than that, our code works pretty much the same way as our <code>ImmutableStack</code>. The only difference is that we must pass the <code>stack</code> variable into every method call.</p>
<p>The above example already follows a functional style, but we can go to one more level of inception. So let's show you that code first:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//stackUtils.js</span>

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">peak</span>(<span class="hljs-params">head</span>) </span>{
  <span class="hljs-keyword">return</span> head?.value;
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pop</span>(<span class="hljs-params">head</span>) </span>{
  <span class="hljs-keyword">const</span> safeNode = head ?? {};

  <span class="hljs-keyword">return</span> safeNode.next;
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">push</span>(<span class="hljs-params">head</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">value</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> node = {
      value,
      <span class="hljs-attr">next</span>: head,
    };
    <span class="hljs-keyword">return</span> node;
  };
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getIterator</span>(<span class="hljs-params">head</span>) </span>{
  <span class="hljs-keyword">return</span> (<span class="hljs-function"><span class="hljs-keyword">function</span>* (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> safeNode = head ?? {};
    <span class="hljs-keyword">while</span> (safeNode.value) {
      <span class="hljs-keyword">yield</span> safeNode.value;
      safeNode = safeNode.next ?? {};
    }
  })();
}

<span class="hljs-comment">// index.js</span>

<span class="hljs-keyword">import</span> { push, pop, peak, getIterator } <span class="hljs-keyword">from</span> <span class="hljs-string">"./stackUtils.js"</span>;

<span class="hljs-keyword">let</span> stack;

stack = push(stack)(<span class="hljs-number">1</span>);
stack = push(stack)(<span class="hljs-number">2</span>);
peak(stack); <span class="hljs-comment">// 2</span>
stack = pop(stack);
peak(stack); <span class="hljs-comment">// 1</span>

stack = push(stack)(<span class="hljs-number">3</span>);
stack = push(stack)(<span class="hljs-number">4</span>);
stack = push(stack)(<span class="hljs-number">2</span>);
<span class="hljs-keyword">let</span> stackPusher = push(stack);

stack = stackPusher(<span class="hljs-number">2</span>);

<span class="hljs-built_in">console</span>.log([...getIterator(stack)]); <span class="hljs-comment">// [ 2, 2, 4, 3, 1 ]</span>
</code></pre>
<p>First, it is more common in FP languages to group related functions in a module, so that was the first thing we did. We move all the methods into simple functions that we export from the<code>stackUtils.js</code> file.</p>
<p>Generally speaking, all the functions work the same way except for the <code>push</code> function. A common functional programming pattern is only one parameter per function. If you need more than one argument, you use a pattern called <em>"currying."</em> When you curry functions, your function will return a new function that requires the next argument. You keep doing this until you no longer need any arguments.</p>
<p>In our <code>push</code> function. We take an argument called <code>head</code> and return a new function that takes an argument called <code>value.</code> When we call that second function, it will still have access to that <code>head</code> value and can complete the code we need to run.</p>
<p>One of the things this gives us is the ability to do "partial application." On one of the lines near the end, we create a new function <code>stackPusher,</code> that will take a value and push it onto a new stack.</p>
<p>This gives us two things we can do. We may know which stack we want to push onto in one part of our code, but we don't yet know the value. Instead of trying to keep track of the stack in some global store, we can pass around a function that already knows which stack to use and needs to have a value passed in:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> stackPusher = push(stack)

<span class="hljs-comment">/* later in our code */</span>

<span class="hljs-keyword">const</span> newStack = stackPusher(<span class="hljs-number">5</span>)
</code></pre>
<p>This can be helpful if we want to create multiple stacks with the same tail but with different heads. We can create a function from the push function that we can use to generate multiple lists with the same tail using different values:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> stackPusher = push(stack)

<span class="hljs-keyword">const</span> stack1 = stackPusher(<span class="hljs-number">5</span>)  
<span class="hljs-keyword">const</span> stack2 = stackPusher(<span class="hljs-number">2</span>)  
<span class="hljs-keyword">const</span> stack3 = stackPusher(<span class="hljs-number">3</span>)  
<span class="hljs-keyword">const</span> stack4 = stackPusher(<span class="hljs-number">8</span>)  
<span class="hljs-keyword">const</span> stack5 = stackPusher(<span class="hljs-number">12</span>)
</code></pre>
<p>So there are four styles of code that you can use to do the same thing. One is a typical OO style, and the last is a distinctive FP style with all the variations in between. I recommend trying all these styles out and seeing which makes the most sense.</p>
]]></content:encoded></item><item><title><![CDATA[The Evolution of a Custom React Hook]]></title><description><![CDATA[Photo by Suzanne D. Williams on Unsplash
Abstracting code is a common thing we do in programming. It is also very common for those abstractions to evolve as the requirements change. Recently I had to opportunity to rapidly evolve a React hook from on...]]></description><link>https://non-traditional.dev/the-evolution-of-a-custom-react-hook-3fc0b1f2a6d7</link><guid isPermaLink="true">https://non-traditional.dev/the-evolution-of-a-custom-react-hook-3fc0b1f2a6d7</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[React]]></category><category><![CDATA[ReactHooks]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Mon, 22 Nov 2021 18:13:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638316711210/suq--2SBg.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@scw1217?utm_source=medium&amp;utm_medium=referral">Suzanne D. Williams</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>Abstracting code is a common thing we do in programming. It is also very common for those abstractions to evolve as the requirements change. Recently I had to opportunity to rapidly evolve a React hook from one form to another in the same day. Now that I have finished it, I thought I would share that evolution with you.</p>
<p>The first requirement was that I needed a generic way to poll data in a React component. If you are not familiar with the term, polling means checking data at a regular interval. This first version looked like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useRef, useEffect, useLayoutEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">usePolling</span>(<span class="hljs-params">callBack, intervalTime = <span class="hljs-number">10</span>_000</span>) </span>{
  <span class="hljs-keyword">const</span> callBackRef = useRef(callBack);

  useLayoutEffect(<span class="hljs-function">() =&gt;</span> {
    callBackRef.current = callBack;
  });

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> interval = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> callBackRef.current(), intervalTime);

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">clearInterval</span>(interval);
    };
  }, [callBackRef, intervalTime]);
}
</code></pre>
<p>In the above hook, we take a callback and an optional interval time. This callback will be called at a regular interval determined by the interval time provided in the second parameter, set to 10,000 by default.</p>
<p>The first thing that we are doing is using the <code>useRef</code> hook to create a <code>callBackRef</code> and then we are using the <code>useLayoutEffect</code> to keep the ref current with any changes to the callback. Kent C Dodds well documents this pattern, but to summarize, This pattern allows the callback to stay up to date without causing the useEffect to have to rerun or requiring the user of the hook to wrap the callback in a <code>useCallback</code> hook.</p>
<p>In the second part of the hook, we are using a <code>useEffect</code> hook to start our interval, and then we clean up the hook in the clean-up function returned from the useEffect.</p>
<p>This hook works great, but then I got a new requirement that it needs only to poll when the tab is visible; this would ensure that we are not wasting resources polling data when the user isn't actively using the tab.</p>
<p>Luckily there is an easy way to do this. First of all, the <code>document</code> object has a <code>visibilityState</code> that will let you know if it is <code>visible</code> or <code>hidden.</code> There is also an event listener that we can tap into called <code>visibilitychange</code> that we can use to react to the visibility state changing. <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilitychange_event">Both of these are well documented at MDN.</a></p>
<p>So let's make a tweek to our hook:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useRef, useEffect, useLayoutEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">usePollWhenVisible</span>(<span class="hljs-params">callBack, intervalTime = <span class="hljs-number">10</span>_000</span>) </span>{
  <span class="hljs-keyword">const</span> callBackRef = useRef(callBack);

  useLayoutEffect(<span class="hljs-function">() =&gt;</span> {
    callBackRef.current = callBack;
  });

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

    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">document</span>.visibilityState === <span class="hljs-string">"visible"</span>) {
      interval = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> callBackRef.current(), intervalTime);
    }

    <span class="hljs-keyword">const</span> handleVisibilityChange = <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">clearInterval</span>(interval);
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">document</span>.visibilityState === <span class="hljs-string">"visible"</span>) {
        interval = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> callBackRef.current(), intervalTime);
      }
    };

    <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"visibilitychange"</span>, handleVisibilityChange);

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">clearInterval</span>(interval);
      <span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">"visibilitychange"</span>, handleVisibilityChange);
    };
  }, [callBackRef, intervalTime]);
}
</code></pre>
<p>In the above code, we have changed the internals of our <code>useEffect</code> hook. First of all, we start by declaring the <code>interval</code> variable without defining it, and we declare it using a <code>let.</code> The reason we are doing this will be more apparent why we are doing as we go.</p>
<p>The next thing we are doing is checking if our current visibility state is <code>visible</code> and if it is, we start our interval just as before. This will ensure that we don't begin our interval if the page is no longer visible when the component mounts.</p>
<p>Next, we are defining our event listener function: <code>handleVisibilityChange.</code> This function will be called whenever the visibility state changes. In this function, the first thing we are doing is clearing the interval. This is safe because if the value passed in is not a valid interval, the function will ignore it. After we earn the interval we are doing the same visibility check as above and conditionally starting the interval if the visibility state is <code>visible.</code></p>
<p>Finally, we add our event listener function to the <code>visibilitychange</code> event.</p>
<p>In our clean-up function, we do two things now. First, we clear the interval to ensure that we don't have a memory leak, but secondly, we also remove our event listener so it won't run.</p>
<p>Our hook is working fantastically now, but then a new requirement came down from the requirements gods. This hook will be used in multiple components, but we need them all to be on the same interval cycle. In other words, we need all our hooks to be synchronized.</p>
<p>To do this, I made this last final set of changes:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">const</span> INTERVAL_TIME = <span class="hljs-number">10</span>_000;

<span class="hljs-keyword">let</span> callbacks = [];

<span class="hljs-keyword">let</span> interval;

<span class="hljs-keyword">let</span> handleVisibilityChange;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">init</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (handleVisibilityChange) <span class="hljs-keyword">return</span>;

  interval = <span class="hljs-built_in">setInterval</span>(
    <span class="hljs-function">() =&gt;</span> callbacks.forEach(<span class="hljs-function">(<span class="hljs-params">fn</span>) =&gt;</span> <span class="hljs-keyword">void</span> fn()),
    INTERVAL_TIME
  );

  handleVisibilityChange = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">clearInterval</span>(interval);
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">document</span>.visibilityState === <span class="hljs-string">"visible"</span>) {
      interval = <span class="hljs-built_in">setInterval</span>(
        <span class="hljs-function">() =&gt;</span> callbacks.forEach(<span class="hljs-function">(<span class="hljs-params">fn</span>) =&gt;</span> <span class="hljs-keyword">void</span> fn()),
        INTERVAL_TIME
      );
    }
  };

  <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"visibilitychange"</span>, handleVisibilityChange);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cleanUp</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (callbacks.length &gt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;

  <span class="hljs-keyword">if</span> (handleVisibilityChange) {
    <span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">"visibilitychange"</span>, handleVisibilityChange);
  }

  handleVisibilityChange = <span class="hljs-literal">undefined</span>;
  <span class="hljs-built_in">clearInterval</span>(interval);
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">usePollWhenVisible</span>(<span class="hljs-params">callback</span>) </span>{
  useEffect(<span class="hljs-function">() =&gt;</span> {
    init();

    callbacks = callbacks.concat(callback);

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      callbacks = callbacks.filter(<span class="hljs-function">(<span class="hljs-params">fn</span>) =&gt;</span> fn !== callback);

      cleanUp();
    };
  }, [callback]);
}
</code></pre>
<p>Let's break all this down, part by part.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> INTERVAL_TIME = <span class="hljs-number">10</span>_000;
<span class="hljs-keyword">let</span> callbacks = [];
<span class="hljs-keyword">let</span> interval;
<span class="hljs-keyword">let</span> handleVisibilityChange;
</code></pre>
<p>First, we lifted the <code>interval</code> and <code>handleVisibilityChange</code> functions in the module and out of the hook itself. We have also declared two new variables: <code>callbacks</code> and <code>INTERVAL_TIME.</code></p>
<p>The <code>callbacks</code> variable is initialized with an empty array. This is where we will maintain our list of callbacks to run each interval cycle. Since we now need all the callbacks to be on the same interval cycle, we are now declaring a constant <code>INTERVAL_TIME</code> that we can use universally in our module.</p>
<p>The next thing we do is declare a <code>init</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">init</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (handleVisibilityChange) <span class="hljs-keyword">return</span>;
  interval = <span class="hljs-built_in">setInterval</span>(
    <span class="hljs-function">() =&gt;</span> callbacks.forEach(<span class="hljs-function">(<span class="hljs-params">fn</span>) =&gt;</span> <span class="hljs-keyword">void</span> fn()),
    INTERVAL_TIME
  );

  handleVisibilityChange = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">clearInterval</span>(interval);
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">document</span>.visibilityState === <span class="hljs-string">"visible"</span>) {
      interval = <span class="hljs-built_in">setInterval</span>(
        <span class="hljs-function">() =&gt;</span> callbacks.forEach(<span class="hljs-function">(<span class="hljs-params">fn</span>) =&gt;</span> <span class="hljs-keyword">void</span> fn()),
        INTERVAL_TIME
      );
    }
  };

  <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"visibilitychange"</span>, handleVisibilityChange);
}
</code></pre>
<p>This does a few things. First, it checks if the <code>handleVisibilityChange</code> function is truthy. If it is, we are returning early and not running the rest of the function. This ensures that we only initialize once. The rest of the function, we have already seen. We are starting the interval, declaring our event listener function, and registering it with the <code>visibilitychange</code> event listener.</p>
<p>There is one slight change to the interval function. Instead of calling a single function, we cycle through all the callbacks in the callback array and run those functions.</p>
<p>The next thing that we do is declare a cleanup function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cleanUp</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (callbacks.length &gt; <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;

  <span class="hljs-keyword">if</span> (handleVisibilityChange) {
    <span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">"visibilitychange"</span>, handleVisibilityChange);
  }

  handleVisibilityChange = <span class="hljs-literal">undefined</span>;
  <span class="hljs-built_in">clearInterval</span>(interval);
}
</code></pre>
<p>This is doing the opposite of our <code>init</code> function. First, it checks if there are callbacks. If there are, it will return early and not perform the cleanup if there are still registered callbacks. Then after that, it removes the event listener, sets the <code>handleVisibilityChange</code> back to undefined, and clears the interval. We set the <code>handleVisibilityChange</code> back to undefined so that if the component remounts, the <code>init</code> function will rerun.</p>
<p>Finally, we declare our hook:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">usePollWhenVisible</span>(<span class="hljs-params">callback</span>) </span>{
  useEffect(<span class="hljs-function">() =&gt;</span> {
    init();
    callbacks = callbacks.concat(callback);

    <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
      callbacks = callbacks.filter(<span class="hljs-function">(<span class="hljs-params">fn</span>) =&gt;</span> fn !== callback);
      cleanUp();
    };
  }, [callback]);
}
</code></pre>
<p>Now our hook takes a callback, runs <code>init</code> And adds our callback to the callback array. When it cleans up, it removes itself from the array and calls the <code>cleanUp</code> function.</p>
<p>We no longer need to use the callback ref since we no longer care if the effect is rerun when the callback changes. The init and cleanup already have the guards in place not to run needlessly, and the hook itself is simply adding and removing the callback from the callback array.</p>
<p>That's the final version, or at least final as of right now. It's fun to see how a function can change as the requirements do.</p>
]]></content:encoded></item><item><title><![CDATA[Modernizing Code Examples from Books: parseAge]]></title><description><![CDATA[Photo by John Moeses Bauan on Unsplash
My last post on modernizing splat and unsplat were so much fun I thought I would do it again with the following code example in the book, Functional JavaScript, that I decided to do it again. This time we are go...]]></description><link>https://non-traditional.dev/modernizing-code-examples-from-books-parseage-a6a4177d5b38</link><guid isPermaLink="true">https://non-traditional.dev/modernizing-code-examples-from-books-parseage-a6a4177d5b38</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Functional Programming]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Sat, 30 Oct 2021 07:41:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638316503635/liYFgKgg8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@johnmoeses?utm_source=medium&amp;utm_medium=referral">John Moeses Bauan</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p><a target="_blank" href="https://non-traditional.dev/modernizing-code-splat-and-unsplat-78aa9d0dd77f">My last post on modernizing <code>splat</code> and <code>unsplat</code></a> were so much fun I thought I would do it again with the following code example in the book, Functional JavaScript, that I decided to do it again. This time we are going to go over the <code>parseAge</code> function example.</p>
<p>(Reminder, I still would highly encourage you to get the book, so I won't be going over content in the book, except to explain the example)</p>
<p>In the book, we are presented with this example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fail</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(thing);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">warn</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-built_in">console</span>.log([<span class="hljs-string">"WARNING:"</span>, thing].join(<span class="hljs-string">" "</span>));
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">note</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-built_in">console</span>.log([<span class="hljs-string">"NOTE:"</span>, thing].join(<span class="hljs-string">" "</span>));
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseAge</span>(<span class="hljs-params">age</span>) </span>{
  <span class="hljs-keyword">if</span> (!_.isString(age)) fail(<span class="hljs-string">"Expecting a string"</span>);
  <span class="hljs-keyword">var</span> a;

  note(<span class="hljs-string">"Attempting to parse an age"</span>);
  a = <span class="hljs-built_in">parseInt</span>(age, <span class="hljs-number">10</span>);

  <span class="hljs-keyword">if</span> (_.isNaN(a)) {
    warn([<span class="hljs-string">"Could not parse age:"</span>, age].join(<span class="hljs-string">" "</span>));
    a = <span class="hljs-number">0</span>;
  }

  <span class="hljs-keyword">return</span> a;
}
</code></pre>
<p>In the above code, we have a few utility functions: <code>fail,</code> <code>warn,</code> and <code>note.</code> The functions are pretty self-explanatory. The <code>fail</code> function throws an Error of whatever string is passed in and the <code>warn</code> and <code>note</code>logs a string prefixed with “WARNING:” or “NOTE:” respectively.</p>
<p>The <code>parseAge</code> function then uses those functions while it attempts to parse the age of a string passed in. If a value other than a string is passed in, it will fail, and if the string fails to parse a number it will warn that It couldn’t parse age and then return <code>0</code> otherwise, it returns the parsed age value.</p>
<p>The first low-hanging fruit we can update is that we are using <code>console.log</code> for everything. Instead, we can utilize <code>console.warn</code> and <code>console.info</code> to give a bit more meaning to our console logs:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">warn</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-built_in">console</span>.warn([<span class="hljs-string">"WARNING:"</span>, thing].join(<span class="hljs-string">" "</span>));
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">note</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-built_in">console</span>.info([<span class="hljs-string">"NOTE:"</span>, thing].join(<span class="hljs-string">" "</span>));
}
</code></pre>
<p>The other quick update is that we can update our custom string to use template literals instead of joining arrays:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">warn</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">`WARNING: <span class="hljs-subst">${thing}</span>`</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">note</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-built_in">console</span>.info(<span class="hljs-string">`NOTE: <span class="hljs-subst">${thing}</span>`</span>);
}

<span class="hljs-comment">// from the parseAge function body</span>
<span class="hljs-keyword">if</span> (_.isNaN(a)) {
  warn(<span class="hljs-string">`Could not parse age: <span class="hljs-subst">${age}</span>`</span>);
  a = <span class="hljs-number">0</span>;
}
</code></pre>
<p>The next thing we have is a reliance on underscore.js utility functions. One of those is the <code>_.isNaN</code> function. This was important at the time of the book’s writing because the global <code>isNaN</code> function in JavaScript was unreliable and did not work as expected. Luckily, an alternative method was added in ES2015 to the <code>Number</code> object that does the same thing. So let’s update our code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (<span class="hljs-built_in">Number</span>.isNaN(a)) {
  warn(<span class="hljs-string">`Could not parse age: <span class="hljs-subst">${age}</span>`</span>);
  a = <span class="hljs-number">0</span>;
}
</code></pre>
<p>The utility is the <code>_.isString</code> function. This function works well, but sometimes it doesn’t make sense to bring in a whole utility library just for a small part. Plus this is a great opportunity to understand what <code>_.isString</code> is doing under the hood. If you look at the <a target="_blank" href="https://github.com/jashkenas/underscore/blob/master/modules/isString.js">code in github</a> we can see that it is simply doing something like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (toString.call(value) !== <span class="hljs-string">"[object String]"</span>) {
  fail(<span class="hljs-string">"Expecting a string"</span>);
}
</code></pre>
<p>I’ll leave it to you to look into how that works and why this way is used. But if we combine all these things we now have a more modern version:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fail</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(thing);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">warn</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">`WARNING: <span class="hljs-subst">${thing}</span>`</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">note</span>(<span class="hljs-params">thing</span>) </span>{
  <span class="hljs-built_in">console</span>.info(<span class="hljs-string">`NOTE: <span class="hljs-subst">${thing}</span>`</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">assertIsString</span>(<span class="hljs-params">value</span>) </span>{
  <span class="hljs-keyword">if</span> (toString.call(value) !== <span class="hljs-string">"[object String]"</span>) fail(<span class="hljs-string">"Expecting a string"</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseAge</span>(<span class="hljs-params">age</span>) </span>{
  assertIsString(age);

  note(<span class="hljs-string">"Attempting to parse an age"</span>);
  <span class="hljs-keyword">const</span> a = <span class="hljs-built_in">parseInt</span>(age, <span class="hljs-number">10</span>);

  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Number</span>.isNaN(a)) {
    warn(<span class="hljs-string">`Could not parse age: <span class="hljs-subst">${age}</span>`</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
  }

  <span class="hljs-keyword">return</span> a;
}
</code></pre>
<p>Besides what we have already gone over, there are two other changes in the above code. One is simply changing out <code>var</code> to <code>const</code> and pre-emptively returning <code>0</code> if the the parsed value is not a number.</p>
<p>The other change is more stylistic choice, but one I personally like. I refactored out the string check into it’s own function called <code>assertIsString.</code> This is primarily a stylistic choice, but it is also helpful when as we start converting it to TypesScript. Speaking of…</p>
<p>Most of the functions are simply typed:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fail</span>(<span class="hljs-params">thing: string</span>) </span>{
  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(thing);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">warn</span>(<span class="hljs-params">thing: string</span>) </span>{
  <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">`WARNING: <span class="hljs-subst">${thing}</span>`</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">note</span>(<span class="hljs-params">thing: string</span>) </span>{
  <span class="hljs-built_in">console</span>.info(<span class="hljs-string">`NOTE: <span class="hljs-subst">${thing}</span>`</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">assertIsString</span>(<span class="hljs-params">value: unknown</span>) </span>{
  <span class="hljs-keyword">if</span> (toString.call(value) !== <span class="hljs-string">"[object String]"</span>) {
    fail(<span class="hljs-string">"Expecting a string"</span>);
  }
}
</code></pre>
<p><code>fail,</code> <code>warn,</code> and <code>note</code> all take a string, so we added that type to the parameters of each function. <code>assertIsString</code> takes an unknown value and checks if it is a string. So it makes sense for it’s parameter to be of type <code>unknown.</code></p>
<p>As for the <code>parseAge</code> function, it would be safe to assume we should type the parameter as a <code>string,</code> and honestly that would probably be the right choice in most apps. That said, the spirit of how the function is written implies that the value is unknown so let’s use the <code>unknown</code> type.</p>
<p>The problem is that, despite the fact that we are verifying the type of the age parameter is a string in our <code>assertIsString</code> function. TypeScript still will see that the value is unknown and complain when we try to call <code>parseInt</code> with an unknown value.</p>
<p>We could wrap the remaining code in a if statement that check the type of age, but honestly why are we doing another type check just to satisfy TypeScript (plus TypeScript will still complain on not writing code for all potential branches, so we didn’t really solve the problem).</p>
<p>What we need is to somehow let TypeScript know that once we get past the <code>assertIsString</code> function that the age parameter can safely be assumed to be a string at that point. Luckily, TypeScript has a way to do just that. Let’s make one small change to the type of our <code>assertIsString</code> function:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">assertIsString</span>(<span class="hljs-params">value:unknown</span>):<span class="hljs-title">asserts</span> <span class="hljs-title">value</span> <span class="hljs-title">is</span> <span class="hljs-title">string</span> </span>{
 <span class="hljs-keyword">if</span>(toString.call(value) !== <span class="hljs-string">'[object String]'</span>){
 fail(<span class="hljs-string">"Expecting a string"</span>);
 }
}
</code></pre>
<p>In the above code, we added <code>:asserts value is string</code> where we would normally define our return type. What this does is instead of defining a return type from the function, we are telling TypeScript that what ever was passed into the function can be safely be used as a string.</p>
<p>We can do this, because if the value is not a string, we throw an error and the code doesn’t proceed on. If, however, the function runs without errors, we can be confident that it is in fact a string. It is important to note, that TypeScript is taking our word for it. TypeScript isn’t actually looking at our code to see if it works (it would be <a target="_blank" href="https://en.wikipedia.org/wiki/Halting_problem">impossible</a> for it to do so). So you do need to be confident that it is implemented correctly.</p>
<p>Let’s look at the full TypeScript version:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fail</span>(<span class="hljs-params">thing:string</span>)</span>{
  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(thing);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">warn</span>(<span class="hljs-params">thing:string</span>)</span>{
  <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">`WARNING: <span class="hljs-subst">${thing}</span>`</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">note</span>(<span class="hljs-params">thing:string</span>)</span>{
  <span class="hljs-built_in">console</span>.info = <span class="hljs-built_in">console</span>.log
  <span class="hljs-built_in">console</span>.info(<span class="hljs-string">`NOTE: <span class="hljs-subst">${thing}</span>`</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">assertIsString</span>(<span class="hljs-params">value:unknown</span>):<span class="hljs-title">asserts</span> <span class="hljs-title">value</span> <span class="hljs-title">is</span> <span class="hljs-title">string</span></span>{
  <span class="hljs-keyword">if</span>(toString.call(value) !== <span class="hljs-string">'[object String]'</span>) fail(<span class="hljs-string">"Expecting a string"</span>);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseAge</span>(<span class="hljs-params">age:unknown</span>)</span>{
  assertIsString(age)

  note(<span class="hljs-string">"Attempting to parse an age"</span>);
  <span class="hljs-keyword">const</span> a = <span class="hljs-built_in">parseInt</span>(age, <span class="hljs-number">10</span>)

  <span class="hljs-keyword">if</span>(<span class="hljs-built_in">Number</span>.isNaN(a)){
    warn(<span class="hljs-string">`Could not parse age: <span class="hljs-subst">${age}</span>`</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>
  }

  <span class="hljs-keyword">return</span> a
}
</code></pre>
<p>So there you have it. A fully modernized code example, complete with TypeScript. Let me know what you think and I look forward to sharing more examples with you soon.</p>
]]></content:encoded></item><item><title><![CDATA[Modernizing Code Examples from Books: splat and unsplat]]></title><description><![CDATA[Photo by Pawel Czerwinski on Unsplash
One of my favorite books for JavaScript is “Functional JavaScript” by Michael Fogus. Even though it was written in JavaScript pre-ES2015 and leans heavily on underscore.js, a groundbreaking functional utility lib...]]></description><link>https://non-traditional.dev/modernizing-code-splat-and-unsplat-78aa9d0dd77f</link><guid isPermaLink="true">https://non-traditional.dev/modernizing-code-splat-and-unsplat-78aa9d0dd77f</guid><category><![CDATA[Functional Programming]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Wed, 13 Oct 2021 13:03:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638316745699/JtybighVP.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@pawel_czerwinski?utm_source=medium&amp;utm_medium=referral">Pawel Czerwinski</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>One of my favorite books for JavaScript is “Functional JavaScript” by Michael Fogus. Even though it was written in JavaScript pre-ES2015 and leans heavily on underscore.js, a groundbreaking functional utility library that has since lost much of its market share, the core concepts taught in the book stand the test of time and show you how to think like a functional JavaScript Programmer.</p>
<p>That said, the examples are out of date. More and more new developers will have a more challenging time reading the code examples or even knowing how to apply the examples in a modern codebase, especially one written in TypeScript.</p>
<p>So I thought it would be a great exercise, to slowly update the examples here so that they show more modern styles of JavaScript while hopefully extending the life of this great resource that is available to the community.</p>
<p>(In this example, I will only be going over minimum amount of the content from the book as possible. I still highly recommend the book,, and I want to encourage you to buy it and use it as a resource.)</p>
<p>So the first example shown is splat and unsplat, two contrived utility functions:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">splat</span>(<span class="hljs-params">fun</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">array</span>) </span>{
    <span class="hljs-keyword">return</span> fun.apply(<span class="hljs-literal">null</span>, array);
  };
}

<span class="hljs-keyword">var</span> addArrayElements = splat(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">x, y</span>) </span>{
  <span class="hljs-keyword">return</span> x + y;
});

addArrayElements([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>]);
<span class="hljs-comment">//=&gt; 3</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unsplat</span>(<span class="hljs-params">fun</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> fun.call(<span class="hljs-literal">null</span>, _.toArray(<span class="hljs-built_in">arguments</span>));
  };
}

<span class="hljs-keyword">var</span> joinElements = unsplat(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">array</span>) </span>{
  <span class="hljs-keyword">return</span> array.join(<span class="hljs-string">" "</span>);
});

joinElements(<span class="hljs-string">"-"</span>, <span class="hljs-string">"$"</span>, <span class="hljs-string">"/"</span>, <span class="hljs-string">"!"</span>, <span class="hljs-string">":"</span>);
<span class="hljs-comment">//=&gt; '- $ / ! :'</span>
</code></pre>
<p>To summarize the above, we are creating two utility functions: <code>splat</code> and <code>unsplat</code>. Both take a function as an argument and return a new function, a pattern known as higher-order functions.</p>
<p><code>splat</code> takes a function and returns a new function that accepts an array of values. Each value will be applied as an argument to the provided function.</p>
<p><code>unsplat,</code> takes an inverse approach to its <code>splat</code> counterpart. It takes a function that accepts an array as its argument and returns a function that will convert all the arguments passed into an array and apply that array to the provided function.</p>
<p>(Once again, for more details, please refer to the book.)</p>
<p>The first thing we can do is update the implementation of how <code>splat</code> and <code>unsplat</code> work under the hood. <code>splat</code> takes advantage of <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply">the</a><code>[apply](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)</code> <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply">method</a> provided that is part of all functions in JavaScript. Simply put, apply takes a context (which isn’t essential in this use case, hence why <code>null</code>is used) and an array of values. Each value in the array is applied as an argument to the function.</p>
<p><code>unsplat</code> is similar, but it is implemented using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call">the</a> <code>[call](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)</code> <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call">method</a> provided on all JavaScript functions. Like <code>apply,</code> it takes a context, but instead of an array of values, all the remaining arguments supplied to the <code>call</code> method will be passed as arguments to the function.</p>
<p>Using call and apply was great when that was the only thing you could do, but we now have access to the spread and rest operators in modern JavaScript. The spread operator will let you spread the values of an array out as arguments to any function. This means we can update our <code>splat</code> function to look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">splat</span>(<span class="hljs-params">fun</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">array</span>) </span>{
    <span class="hljs-keyword">return</span> fun(...array);
  };
}
</code></pre>
<p>The <code>unsplat</code> function can also be updated similarly. In the old example we were using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments">the</a> <code>[arguments](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments)</code> <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments">object</a>, which is an object that looks like an array, but isn’t one. So it has to be converted to an array (the book’s example uses the underscore utility function to do that). Now that we have the rest operator we can bundle all the arguments into a single array, without needing to convert it, like this:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unsplat</span>(<span class="hljs-params">fun</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">...args</span>) </span>{
    <span class="hljs-keyword">return</span> fun(args);
  };
}
</code></pre>
<p>This is more readable and easy to understand, but we also don’t have to worry about the context, which was not necessary for what we were doing.</p>
<p>This is great already, but we are still only using one form of writing our functions. With ES2015 we also have an arrow function syntax that gives us more flexibility on how we write our functions. <a target="_blank" href="https://non-traditional.dev/opinionated-javascript-4585b4b353e6">I’ve given my opinions</a> on JavaScript in an earlier post, but I never shared my opinions on function declarations.</p>
<p>I simply have two rules, named functions should prefer the traditional function declaration syntax and anonymous functions should prefer arrow function syntax. Also one should prefer the implicit return syntax if the return value is simple and easy to fit on one line. With that, we can update the entire file to look like this:</p>
<pre><code class="lang-jsx"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">splat</span>(<span class="hljs-params">fun</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">array</span>) =&gt;</span> fun(...array);
}

<span class="hljs-keyword">const</span> addArrayElements = splat(<span class="hljs-function">(<span class="hljs-params">x, y</span>) =&gt;</span> x + y);

addArrayElements([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>]);
<span class="hljs-comment">//=&gt; 3</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unsplat</span>(<span class="hljs-params">fun</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">...args</span>) =&gt;</span> fun(args);
}

<span class="hljs-keyword">const</span> joinElements = unsplat(<span class="hljs-function">(<span class="hljs-params">array</span>) =&gt;</span> array.join(<span class="hljs-string">" "</span>));

joinElements(<span class="hljs-string">"-"</span>, <span class="hljs-string">"$"</span>, <span class="hljs-string">"/"</span>, <span class="hljs-string">"!"</span>, <span class="hljs-string">":"</span>);
<span class="hljs-comment">//=&gt; '- $ / ! :'</span>
</code></pre>
<p>Finally, let’s add some type safety to our new functions. I’ve already written a post about <a target="_blank" href="https://non-traditional.dev/dynamic-typing-in-typescript-using-generics-f88fa52428cb">Dynamic typing using Generics</a>, which luckily translates very well to these two functions. So let’s update them now to use Typescript:</p>
<pre><code class="lang-typescript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">splat</span>&lt;<span class="hljs-title">T</span> <span class="hljs-title">extends</span> <span class="hljs-title">Array</span>&lt;<span class="hljs-title">unknown</span>&gt;, <span class="hljs-title">R</span> = <span class="hljs-title">unknown</span>&gt;(<span class="hljs-params">
  fun: (...arr: T) =&gt; R
</span>): (<span class="hljs-params">arr: T</span>) =&gt; <span class="hljs-title">R</span> </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">array</span>) =&gt;</span> fun(...array);
}

<span class="hljs-keyword">const</span> addArrayElements = splat(<span class="hljs-function">(<span class="hljs-params">x: <span class="hljs-built_in">number</span>, y: <span class="hljs-built_in">number</span></span>) =&gt;</span> x + y);

addArrayElements([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>]);
<span class="hljs-comment">//=&gt; 3</span>

addArrayElements([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]); <span class="hljs-comment">//TS Error</span>
addArrayElements([<span class="hljs-number">1</span>]); <span class="hljs-comment">//TS Error</span>
addArrayElements([<span class="hljs-string">"1"</span>, <span class="hljs-string">"2"</span>]); <span class="hljs-comment">//TS Error</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unsplat</span>&lt;<span class="hljs-title">T</span> <span class="hljs-title">extends</span> <span class="hljs-title">Array</span>&lt;<span class="hljs-title">unknown</span>&gt;, <span class="hljs-title">R</span> = <span class="hljs-title">unknown</span>&gt;(<span class="hljs-params">
  fun: (arr: T) =&gt; R
</span>): (<span class="hljs-params">...arr: T</span>) =&gt; <span class="hljs-title">R</span> </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-function">(<span class="hljs-params">...args</span>) =&gt;</span> fun(args);
}

<span class="hljs-keyword">const</span> joinElements = unsplat(<span class="hljs-function">(<span class="hljs-params">array</span>) =&gt;</span> array.join(<span class="hljs-string">" "</span>));

joinElements(<span class="hljs-string">"-"</span>, <span class="hljs-string">"$"</span>, <span class="hljs-string">"/"</span>, <span class="hljs-string">"!"</span>, <span class="hljs-string">":"</span>);
<span class="hljs-comment">//=&gt; '- $ / ! :'</span>
</code></pre>
<p>There we have it. We have successfully updated the first code example to use a modern form of functional JavaScript. I will be sharing some more examples as I re-read the book from the beginning, but this should help you be able to look at code examples from older books and update them to modern JavaScript.</p>
]]></content:encoded></item><item><title><![CDATA[Finding Your Online Dev Community]]></title><description><![CDATA[Photo by "My Life Through A Lens" on Unsplash
When trying to break in as a web developer, one of the things that helped me get started was the local meetup. Once a month, I could meet other like-minded individuals of various abilities, and we would a...]]></description><link>https://non-traditional.dev/finding-your-online-dev-community-42a7b8b5d819</link><guid isPermaLink="true">https://non-traditional.dev/finding-your-online-dev-community-42a7b8b5d819</guid><category><![CDATA[community]]></category><category><![CDATA[Developer]]></category><category><![CDATA[DEVCommunity]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Mon, 30 Aug 2021 16:58:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638316513162/fn-7fWVRD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@bamagal?utm_source=medium&amp;utm_medium=referral">"My Life Through A Lens"</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>When trying to break in as a web developer, one of the things that helped me get started was the local meetup. Once a month, I could meet other like-minded individuals of various abilities, and we would all learn together.</p>
<p>Fast forward to 2021, and things have changed. More and more things have moved to online communities, and with the pandemic accelerating the adoption of virtual solutions to do that thing.</p>
<p><a target="_blank" href="https://medium.com/u/46b6f430560f">Juan Cruz Martinez</a> has made <a target="_blank" href="https://levelup.gitconnected.com/top-10-online-developer-communities-6b0ffdce854c"><strong>a list of Developer communities</strong></a> that are worth checking out. But I thought I would go into what I feel are good things to look for in a developer community. And to help me, I plan on highlighting things from my favorite developer community: <a target="_blank" href="https://t.co/9Nfuy36oOk?amp=1">The Lunch.dev Discord Server.</a></p>
<h3 id="heading-sincerely-welcoming">Sincerely Welcoming</h3>
<p>One of the great things about the Lunch.dev Discord Server is that everyone is sincerely welcoming. There isn’t an individual that joins that isn’t welcomed by name in the main general chat. Each welcome is sincere and brings with it an encouragement to start participating if so desired.</p>
<p>I have also seen Michael Chan, the creator of the server, personally reach out and take the time to get to know new individuals and try to understand their goals.</p>
<p><strong>A good community will find a way to make you sincerely feel welcomed to be a part of it.</strong></p>
<h3 id="heading-resource-of-knowledge-and-growth">Resource of Knowledge and Growth</h3>
<p>The Lunch.dev server was originally called the React Podcast Discord Server. Despite its name coming from the React Podcast, the community is not necessarily focused on React. It focuses more on creating an environment where people can safely ask for help from others without fear of toxic replies.</p>
<p>It also encourages others to share things they have learned about any subject, including frameworks other than React. The server regularly promotes events where community members can learn from each other. Events include book clubs, lightning talks, round tables, and lunch and learn.</p>
<p><strong>A good community will provide and encourage you to grow as a developer and a person.</strong></p>
<h3 id="heading-encourages-healthy-self-promotion">Encourages Healthy Self-Promotion</h3>
<p>The previous section implied it, but I think it’s important enough to call out right now. Sharing information often includes sharing content that you have created yourself.</p>
<p>On the Lunch.dev server, people regularly share blog posts, twitch streams, Twitter threads, and podcasts that they participate in. Not only is this self-promotion not looked down on, it is also encouraged. There are dedicated channels to do just that, showcase what you have been working on.</p>
<p><strong>A good community will acknowledge that not all self-promotion is spam and will encourage users to share, in a healthy way, what they are doing that makes them awesome.</strong></p>
<p>One can look for many things in a community, but these three I feel are important when looking for and evaluating any community that you are looking to join or create yourself.</p>
]]></content:encoded></item><item><title><![CDATA[Why Every Developer Should Start Creating Content]]></title><description><![CDATA[Photo by Nick Fewings on Unsplash
Looking back at how my career has shaped, I can point to one moment where I feel it took off. The moment I started writing blog posts. Not that my career had become stagnant, but it rocketed up quickly the moment I s...]]></description><link>https://non-traditional.dev/why-every-developer-should-start-creating-content-ba008cd264c2</link><guid isPermaLink="true">https://non-traditional.dev/why-every-developer-should-start-creating-content-ba008cd264c2</guid><category><![CDATA[#codenewbies]]></category><category><![CDATA[content]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Fri, 20 Aug 2021 23:01:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638316507626/bg38LAwD-.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@jannerboy62?utm_source=medium&amp;utm_medium=referral">Nick Fewings</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>Looking back at how my career has shaped, I can point to one moment where I feel it took off. The moment I started writing blog posts. Not that my career had become stagnant, but it rocketed up quickly the moment I started putting thoughts on virtual paper and presented them for the world.</p>
<p>In hind sight, I feel there are a few reasons why that happened. And it’s why I think every developer should look at creating content, no matter if it is writing in a blog, streaming on twitch, making YouTube videos, or all of the above.</p>
<h3 id="heading-content-becomes-your-portfolio">Content Becomes Your Portfolio</h3>
<p>Trying to break into this career, I spent all my free time building hobby projects and such to prove I could start contributing right away. It was a great representation of my work during that snap shot in time. Once I started working “real” developer jobs, that portfolio was no longer representative of my skills and I needed to stop showing them to potential employers.</p>
<p>The problem was that, the code I was writing wasn’t able to be shown to new employers. It was all behind private repos. As you move up, it is just as important to show you understand higher level concepts and not just technical syntax.</p>
<p>That is where content creation can easily step in and become your new portfolio. Code examples and the explanations for them more accurately show your programming abilities than random projects on Github will. It shows that not only can you do something, you can communicate why.</p>
<h3 id="heading-content-helps-you-learn">Content Helps You Learn</h3>
<p>Sometimes I wrote content, because I learned something cool and wanted to share it. Just as often, I wrote content because I wanted a reason to learn something.</p>
<p>For example, early on in my blog writing career, I decided I really wanted to understand generator functions and why they existed in the first place. I decided I wrote a blog post title called <a target="_blank" href="http://How%20To%20Code%20The%20“Fizz%20Buzz”%20Challenge%20Using%20JavaScript%20Generators">“How To Code The “Fizz Buzz” Challenge Using JavaScript Generators”</a>. I hadn’t even figured out what the content would be at that point, but it gave me a reason to dive deeper and is still one of my favorite blog posts I have written.</p>
<p>I also learned a lot from people who commented on my blog posts. Yes there is a stupid Troll sometimes, and even others who have legit comments, but have zero ability to criticize nicely. Overall, comments have been a source of knowledge to me and helped refine my knowledge even further.</p>
<h3 id="heading-how-to-get-started">How To Get Started</h3>
<p><a target="_blank" href="https://medium.com/u/182a20ed52f4">Carla Urrea Stabile</a> wrote a <a target="_blank" href="https://carlastabile.medium.com/how-to-start-creating-content-as-a-software-developer-7989dc456742">great post about it</a> over at her blog. The biggest thing is just start. I was thinking about streaming on twitch for a while now, but it wasn’t until my friend, Ben Meyers who streams over at SomeAnticsDev, the biggest thing you need to do to get started is just start. And then when you are done, do it again. And then do it again. You get better as you go, the hardest part is get started.</p>
]]></content:encoded></item><item><title><![CDATA[My Variable Naming Scheme in JavaScript]]></title><description><![CDATA[Photo by Jon Tyson on Unsplash
Naming things in programming is very difficult. In a previous post, I talked about my opinions when writing JavaScript. I recently read about what not to do when naming variables by John Au-Yeung and I very much agreed ...]]></description><link>https://non-traditional.dev/my-variable-naming-scheme-in-javascript-c0a3f1f2dfb8</link><guid isPermaLink="true">https://non-traditional.dev/my-variable-naming-scheme-in-javascript-c0a3f1f2dfb8</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Travis Waith-Mair]]></dc:creator><pubDate>Thu, 12 Aug 2021 20:55:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638316574825/utMA6o-ma.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@jontyson?utm_source=medium&amp;utm_medium=referral">Jon Tyson</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>Naming things in programming is very difficult. In a previous post, <a target="_blank" href="https://non-traditional.dev/opinionated-javascript-4585b4b353e6">I talked about my opinions when writing JavaScript.</a> I recently read about <a target="_blank" href="https://levelup.gitconnected.com/javascript-best-practices-variable-names-to-avoid-18f7cb47b5bb">what not to do when naming variables</a> by <a target="_blank" href="https://medium.com/u/5253c50d76c1">John Au-Yeung</a> and I very much agreed with many of the points.</p>
<p>It made me realize that my previous post lacked some essential naming patterns that I like to adopt. Yes, naming things can be hard, but it can make it much easier to name things in our code if you have a naming scheme that you follow. So I thought I would share my personal rules here in this post.</p>
<h3 id="heading-functions-and-method-names-should-be-verbs">Functions and Method Names Should be Verbs</h3>
<p>Functions and methods are actions that are being performed. So it goes to reason that they should be names that describe that action. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkOnlineStatus</span>(<span class="hljs-params"></span>) </span>{}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUserDetails</span>(<span class="hljs-params">userId</span>) </span>{}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeDuplicates</span>(<span class="hljs-params">array</span>) </span>{}
</code></pre>
<p>Naming functions this way clearly communicate what each of the functions does and even that they are functions in the first place. As things get passed around, it can get easy to lose track of what things are. Using an action verb helps communicate that this is something that needs to be called.</p>
<p>The one exception to this rule is old school JavaScript constructors, which were just functions called using the <code>new</code> operator, and React Components. In both cases, the functions are actually being used to create Objects, which leads me to my next rule.</p>
<h3 id="heading-objects-and-primitives-should-be-nouns">Objects and Primitives Should be Nouns</h3>
<p>Variables that are assigned objects or primitive values represent something that has substance. It makes sense that we should use nouns to name these items of substance. For example:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> userAge = <span class="hljs-number">12</span>;

<span class="hljs-keyword">const</span> admin = {
  <span class="hljs-attr">name</span>: <span class="hljs-string">"Doe, John"</span>,
};

<span class="hljs-keyword">const</span> hostCity = <span class="hljs-string">"Salt Lake City, Ut"</span>;
</code></pre>
<p>It also makes it clear when you return values from functions that they should be named nouns that correspond with the function:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> onlineStatus = checkOnlineStatus();

<span class="hljs-keyword">const</span> currentUser = getUser(userId);
</code></pre>
<h3 id="heading-arrays-should-be-plural-nouns">Arrays Should be Plural Nouns</h3>
<p>Arrays are technically Objects in JavaScript, but they are unique in that they represent a list of things. So it makes sense that arrays should be a pluralized form of that noun.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> friends = [
  <span class="hljs-comment">/*...*/</span>
];

<span class="hljs-keyword">const</span> names = [
  <span class="hljs-comment">/*...*/</span>
];

<span class="hljs-keyword">const</span> indexes = [
  <span class="hljs-comment">/*...*/</span>
];
</code></pre>
<p>It also makes the parameter used in the callbacks of array methods easier to name as well. Simply use the singular form:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> friendNames = friends.map(<span class="hljs-function">(<span class="hljs-params">friend</span>) =&gt;</span> friend.name);
</code></pre>
<h3 id="heading-objects-used-as-keyvalue-pairs-should-use-the-suffix-map">Objects Used as Key/Value Pairs Should Use The Suffix <code>Map</code></h3>
<p>JavaScript objects are pretty versatile. Besides representing things like users, they are also often used to map pairs of keys and values. In those cases, the variable name should also make sure that it is clear:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> spacingMap = {
  <span class="hljs-attr">xs</span>: <span class="hljs-string">"0.125rem"</span>,
  <span class="hljs-attr">sm</span>: <span class="hljs-string">"0.25rem"</span>,
  <span class="hljs-attr">md</span>: <span class="hljs-string">"0.5rem"</span>,
  <span class="hljs-attr">lg</span>: <span class="hljs-string">"1rem"</span>,
  <span class="hljs-attr">xl</span>: <span class="hljs-string">"2rem"</span>,
  <span class="hljs-attr">xxl</span>: <span class="hljs-string">"4rem"</span>,
};
</code></pre>
<p>Now it’s clear that each key will be mapped to a spacing value that I will need.</p>
<h3 id="heading-nullable-values-should-be-prefixed-with-maybe">Nullable Values Should be Prefixed With <code>Maybe</code></h3>
<p>If a value could be undefined or null, you want to communicate that in your variable name. This makes it clear that when using that variable, that you need to write defensive guards that handle what happens when the variable is nullish:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> maybeHostCity = findHostCityByState(<span class="hljs-string">"ND"</span>);
</code></pre>
<p>It is clear that we are expecting a host city, but it might be null, so we can be sure to guard for that case in our code.</p>
<p>Setting up your own naming scheme will make it much easier to name things in the future, and naming things correctly can make your code easier to read and maintain.</p>
]]></content:encoded></item></channel></rss>