<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gabriel Abud</title>
    <description>The latest articles on DEV Community by Gabriel Abud (@g_abud).</description>
    <link>https://dev.to/g_abud</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F396467%2F4e5ab5dd-4b59-442a-93ca-e39e5d696848.png</url>
      <title>DEV Community: Gabriel Abud</title>
      <link>https://dev.to/g_abud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/g_abud"/>
    <language>en</language>
    <item>
      <title>10 Things I Learned by Making a React Hook Library</title>
      <dc:creator>Gabriel Abud</dc:creator>
      <pubDate>Wed, 26 Aug 2020 16:17:04 +0000</pubDate>
      <link>https://dev.to/g_abud/10-things-i-learned-by-making-a-react-hook-library-4i0a</link>
      <guid>https://dev.to/g_abud/10-things-i-learned-by-making-a-react-hook-library-4i0a</guid>
      <description>&lt;p&gt;Since the introduction of &lt;a href="https://reactjs.org/docs/hooks-intro.html"&gt;Hooks&lt;/a&gt; in React 16.8, there has been &lt;a href="https://github.com/rehooks/awesome-react-hooks"&gt;an explosion of Hook libraries&lt;/a&gt;, and for good reason.  Hooks are how you reuse code in functional components.  Without Hooks, functional components would not be a viable alternative to class based components.&lt;/p&gt;

&lt;p&gt;While I had made custom Hooks before, I had procrastinated making my own React Hook library.  I knew if I made my own custom Hook without making it a library, it would die in the uncompleted side project graveyard that is my Github.  So I needed to make it shareable in order to hold me accountable.&lt;/p&gt;

&lt;h1&gt;
  
  
  What I Built
&lt;/h1&gt;

&lt;p&gt;I was frustrated by the existing table libraries out there.  In most of my projects, I need to show tabular data in one form or another.  While most existing table libraries do a decent job, once you start deviating from the default UI you end up fighting with the library a lot.  These table libraries have a ton of existing issues, because it's hard to present a UI that is truly flexible to all the use cases.  &lt;/p&gt;

&lt;p&gt;What I needed was an easy way to handle the table state with no opinions on the UI.  I stumbled on to the idea of &lt;a href="https://www.merrickchristensen.com/articles/headless-user-interface-components/"&gt;headless components&lt;/a&gt;, which seemed like the perfect fit for what I needed.  In essence, a headless component provides you the tools to manage the state of the component, without giving you an opinionated UI.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introducing React Final Table
&lt;/h1&gt;

&lt;p&gt;Building off of this concept, I came up with &lt;a href="https://github.com/Buuntu/react-final-table"&gt;React Final Table&lt;/a&gt;.  It's an extremely lightweight (1.5KB minzipped and 0 dependencies), type-safe, headless component library that exposes a single hook.  Out of the box, it supports filtering, searching, selection, sorting, and pagination for your tables.  In its most basic form, it looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useTable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-final-table&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;columns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firstName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;First Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Last Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Frodo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Baggins&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Samwise&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Gamgee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyTable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;th&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;thead&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;td&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;tbody&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;table&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://github.com/Buuntu/react-final-table"&gt;the documentation&lt;/a&gt; for more example use cases.&lt;/p&gt;

&lt;p&gt;Without further ado, here are the top things I learned during this process:&lt;/p&gt;

&lt;h1&gt;
  
  
  1. React Hooks are great
&lt;/h1&gt;

&lt;p&gt;The React equivalent to reusable functions are Hooks.  Anywhere that you are duplicating non-UI code across components, you should evaluate whether making a custom Hook is worthwhile.  Some of the most likely candidates are authentication and fetching data.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. TSDX makes development a breeze
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/formium/tsdx"&gt;TSDX&lt;/a&gt; is a library for quick development of Typescript packages.  There is a template for React, which means getting started with a new package takes only a few seconds.  See &lt;a href="https://dev.to/g_abud/publish-a-typescript-package-in-under-10-minutes-4940"&gt;my guide on using TSDX&lt;/a&gt; for more.&lt;/p&gt;

&lt;h1&gt;
  
  
  3. React Testing Library makes testing a breeze
&lt;/h1&gt;

&lt;p&gt;While I'm a big fan of testing in Python, Jest, and even end to end testing with Cypress, I wasn't sure how to best do integration testing on the frontend.  I knew I didn't want to break everything up into unit tests, since what I really want to test is that it works as expected, &lt;em&gt;regardless of the implementation details&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://testing-library.com/docs/react-testing-library/intro"&gt;React Testing Library&lt;/a&gt; makes it easy to test React Hooks without testing the implementation.  This means my tests resemble how people are likely to use my library without being brittle to changes in the codebase.&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Use sandbox examples
&lt;/h1&gt;

&lt;p&gt;While testing is great, it can only get you so far.  Sometimes you need to visually see what's happening as you add features.  For this, it's important to set up a couple of sandbox examples that use your unpublished library.  You can use &lt;code&gt;npm link&lt;/code&gt; (or &lt;code&gt;yarn link&lt;/code&gt;) to link to your unpublished library.  Once you've published a version, you can share Sandbox examples using a link with &lt;a href="https://codesandbox.io"&gt;Codesandbox.io&lt;/a&gt;.  &lt;a href="https://codesandbox.io/s/material-ui-react-final-table-example-sigrz"&gt;Here's an example&lt;/a&gt; of React Final Table using Codesandbox. &lt;/p&gt;

&lt;p&gt;Or better yet, set up &lt;a href="https://storybook.js.org/"&gt;Storybook&lt;/a&gt; with many example use cases.  Storybook allows you to develop many components in isolation along with documentation.&lt;/p&gt;

&lt;h1&gt;
  
  
  5. There is more to Hooks than useState and useEffect
&lt;/h1&gt;

&lt;p&gt;While we all start out overusing Hooks like useState and useEffect, there are many others to be aware of.&lt;/p&gt;

&lt;p&gt;Some of my favorite lesser known Hooks are useReducer (for complex state), useMemo/useCallback (for performance), and useRef (for persisting changes outside of the render lifecycle).  In this library I made heavy use of all of these.&lt;/p&gt;

&lt;h1&gt;
  
  
  6. Headless UI components &amp;gt; UI components
&lt;/h1&gt;

&lt;p&gt;From personal experience, &lt;a href="https://www.merrickchristensen.com/articles/headless-user-interface-components/"&gt;headless UI components&lt;/a&gt; are more resilient to change and easier to refactor.  It might seem convenient to use a pre-made component library with a UI, but think twice if you're going to be customizing it a lot.  It might end up creating more work than you anticipated.&lt;/p&gt;

&lt;h1&gt;
  
  
  7. Use Typescript Generics for flexible libraries
&lt;/h1&gt;

&lt;p&gt;In order to make a flexible Typescript library, I had to be sure I let people store any type of data in their tables.  But how can you do this safely without using type &lt;code&gt;any&lt;/code&gt; everywhere?&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://www.typescriptlang.org/docs/handbook/generics.html"&gt;Generics&lt;/a&gt; come in.  They let us specify the type at runtime and still ensure that Typescript is performing type safety checks.  Here is a code snippet to elaborate on what a Generic is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// this function takes an element of any type and returns that same type&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// number&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  8. Github Actions and continuous integration are essential
&lt;/h1&gt;

&lt;p&gt;If you're not using continuous integration in your personal or work projects, you should definitely start.  I used to be a heavy &lt;a href="https://circleci.com/"&gt;CircleCI&lt;/a&gt; user, but recently I've started to prefer &lt;a href="https://docs.github.com/en/actions"&gt;Github Actions&lt;/a&gt;.  The configuration and integration in Actions is much simpler than CircleCI, and the &lt;a href="https://github.com/marketplace"&gt;pre-built action ecosystem&lt;/a&gt; is much larger.  In React Final Table, besides the ESLint, Prettier, and testing steps, I've added a Github Action to run code coverage and another to publish to NPM automatically, based on commit messages.  This has greatly simplified my development process, as I don't need to manually update the version and publish to npm every time I make a change.&lt;/p&gt;

&lt;h1&gt;
  
  
  9. Learn from open source
&lt;/h1&gt;

&lt;p&gt;I often get ideas around architecture, best practices, and contributing practices from open source projects I like.  Some notable ones I found helpful for this library were &lt;a href="https://github.com/downshift-js/downshift"&gt;downshift&lt;/a&gt;(another headless UI library), &lt;a href="https://github.com/react-hook-form"&gt;react-hook-form&lt;/a&gt;, and &lt;a href="https://github.com/tannerlinsley/react-query"&gt;react-query&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  10. Solve your own problems
&lt;/h1&gt;

&lt;p&gt;The last recommendation I have is to make libraries that will solve a problem you have.  Nothing is more demotivating than creating something you have no need for, so be sure you will be one of the main users of this library.&lt;/p&gt;

&lt;p&gt;By creating things that you need, you will also have a vested interest in your library and are more likely to produce something of higher value.&lt;/p&gt;

</description>
      <category>react</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Build your First Typescript Package in Under 10 Minutes</title>
      <dc:creator>Gabriel Abud</dc:creator>
      <pubDate>Tue, 28 Jul 2020 15:42:30 +0000</pubDate>
      <link>https://dev.to/g_abud/publish-a-typescript-package-in-under-10-minutes-4940</link>
      <guid>https://dev.to/g_abud/publish-a-typescript-package-in-under-10-minutes-4940</guid>
      <description>&lt;p&gt;I've been putting off building my own Typescript packages for a while.&lt;/p&gt;

&lt;p&gt;Not for a lack of ideas, but because I know modern Javascript/Typescript development is a mess.  Just check the size of your node_modules directory after starting a default React project to see what I mean, over 200MB of dependencies just to get started!  Or better yet, try to start a React project without &lt;code&gt;create-react-app&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It would take me days to configure my own Typescript package with Babel, Prettier, Rollup, ESLint, Jest, etc. just the way I want it. Not to mention probably cost me my sanity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhrcithhp57fe2fpc7d0y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhrcithhp57fe2fpc7d0y.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I stumbled onto &lt;a href="https://github.com/formium/tsdx" rel="noopener noreferrer"&gt;TSDX&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After reading the &lt;a href="https://github.com/formium/tsdx/blob/master/README.md" rel="noopener noreferrer"&gt;README&lt;/a&gt;, I was able to publish an npm package complete with tests in &lt;strong&gt;a single evening&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This guide is a simplified version of what I learned publishing my first package.  By the end of this tutorial you should have a published and tested Typescript package in the &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;NPM registry&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  NPM Registry
&lt;/h1&gt;

&lt;p&gt;First you'll need to create an NPM account and configure it to use in your command line.  Start with &lt;a href="https://docs.npmjs.com/creating-a-new-npm-user-account" rel="noopener noreferrer"&gt;this short guide&lt;/a&gt; to configure your account and login via the command line with &lt;code&gt;npm login&lt;/code&gt; if you haven't done so.&lt;/p&gt;

&lt;h1&gt;
  
  
  What we're Building
&lt;/h1&gt;

&lt;p&gt;Since this tutorial is aimed at beginners, we're going to be building something simple.  A reusable React component with Jest tests, types, and Github actions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk36rqjc1wc9ioejidfgl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk36rqjc1wc9ioejidfgl.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Truly awe inspiring, I know.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://codesandbox.io/s/keen-bose-3ymkf" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/Buuntu/toggle" rel="noopener noreferrer"&gt;Final Source Code&lt;/a&gt;
&lt;/h3&gt;

&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;Let's bootstrap our TSDX project from the command line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx tsdx create toggle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the prompt, select React:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3j19syx9mx59jlpxa80z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3j19syx9mx59jlpxa80z.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the dependencies are installed, let's make sure we can start the project in development/watch mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;toggle
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should now have a functioning package!&lt;/p&gt;

&lt;h1&gt;
  
  
  File Structure
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; tree &lt;span class="nt"&gt;-L&lt;/span&gt; 2 &lt;span class="nt"&gt;-I&lt;/span&gt; node_modules
&lt;span class="nb"&gt;.&lt;/span&gt;
├── LICENSE
├── README.md
├── dist
│   ├── index.d.ts
│   ├── index.js
│   ├── toggle.cjs.development.js
│   ├── toggle.cjs.development.js.map
│   ├── toggle.cjs.production.min.js
│   ├── toggle.cjs.production.min.js.map
│   ├── toggle.esm.js
│   └── toggle.esm.js.map
├── example
│   ├── index.html
│   ├── index.tsx
│   ├── package.json
│   └── tsconfig.json
├── package-lock.json
├── package.json
├── src
│   └── index.tsx
├── &lt;span class="nb"&gt;test&lt;/span&gt;
│   └── blah.test.tsx
└── tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default project is pretty minimalist.  There are a few directories/files that are important to know though.&lt;/p&gt;

&lt;h3&gt;
  
  
  Directories
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;src: This is where all of the source files that will be built live&lt;/li&gt;
&lt;li&gt;example: An example playground to test your component/package&lt;/li&gt;
&lt;li&gt;dist: What will get built and published to npm.  You shouldn't really have to touch this directory and it should be excluded from source control.&lt;/li&gt;
&lt;li&gt;test: Your tests&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Files
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;src/index.tsx: Your main source file that will be built.  This needs to import all your other source files&lt;/li&gt;
&lt;li&gt;package.json: Dependencies/all configuration for your package&lt;/li&gt;
&lt;li&gt;example/package.json: Dependencies for your playground (these will not be published to npm)&lt;/li&gt;
&lt;li&gt;example/index.tsx: File that loads your package for the playground&lt;/li&gt;
&lt;li&gt;test/blah.test.tsx: Example test file&lt;/li&gt;
&lt;li&gt;README.md: Generated README with a lot of useful information for reference.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Toggle Component
&lt;/h1&gt;

&lt;p&gt;To keep with React best practices, we'll make a separate file for our component. &lt;/p&gt;

&lt;p&gt;Copy and paste the following code into &lt;code&gt;src/Toggle.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Inside src/Toggle.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Toggle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"switch"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"slider round"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing crazy here, just a default HTML checkbox.  Let's export our component from our &lt;code&gt;index.tsx&lt;/code&gt; file which is the main file that will be used in the package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/index.tsx&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Toggle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TSDX projects come with an example folder to help you visualize your component in a browser.  This is what we'll use as a sandbox for our component as well.  Since we changed the name of the component, we'll have to update the example import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// example/index.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-app-polyfill/ie11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Toggle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 👈 Change our import &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Toggle&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* 👈 Change to use your new component*/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's run this sandbox environment to see what we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;example
npm i
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to &lt;a href="http://localhost:1234" rel="noopener noreferrer"&gt;http://localhost:1234&lt;/a&gt;.  You should see a checkbox!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frcaqsmvqxwh7nftnyheo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frcaqsmvqxwh7nftnyheo.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Styling
&lt;/h1&gt;

&lt;p&gt;Let's add some styles to our sweet checkbox now.  Open a new file called &lt;code&gt;Toggle.css&lt;/code&gt; inside of the src directory and copy the following styles into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* src/Toggle.css */&lt;/span&gt;

&lt;span class="c"&gt;/* The switch - the box around the slider */&lt;/span&gt;
&lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;34px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Hide default HTML checkbox */&lt;/span&gt;
&lt;span class="nc"&gt;.switch&lt;/span&gt; &lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* The slider */&lt;/span&gt;
&lt;span class="nc"&gt;.slider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ccc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.4s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.4s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.slider&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;26px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;26px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.4s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;.4s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.slider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#2196F3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.slider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;#2196F3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;.slider&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;26px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;-ms-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;26px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;26px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Rounded sliders */&lt;/span&gt;
&lt;span class="nc"&gt;.slider.round&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;34px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.slider.round&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's import those styles into our &lt;code&gt;Toggle.tsx&lt;/code&gt; component.  We will need to install the &lt;code&gt;rollup-plugin-postcss&lt;/code&gt; to tell Rollup how to compile CSS as part of our package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; rollup-plugin-postcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create a file called tsdx.config.js in the root of your project and paste the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tsdx.config.js&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postcss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-postcss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;rollup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;postcss&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now we can import our styles using ESM imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/Toggle.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Toggle.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 👈 Import our new styles&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Toggle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"switch"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"slider round"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Save and refresh your browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2pgbzjcxxbaf8s67g5j9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2pgbzjcxxbaf8s67g5j9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tada!&lt;/p&gt;

&lt;h1&gt;
  
  
  Component Props
&lt;/h1&gt;

&lt;p&gt;But what if we want to actually do something with the state of our toggle component?  It's not very useful as is.&lt;/p&gt;

&lt;p&gt;Let's add component props in order to give us more flexibility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/Toggle.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Toggle.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ToggleType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;isOn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Toggle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FC&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ToggleType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isOn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"switch"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isOn&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"slider round"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can now pass props into the component and manage the state of it.  Our types will automatically be built and included as part of our project, since we are exporting &lt;code&gt;ToggleType&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's update our playground to contain this state and make sure the toggle still works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// example/index.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-app-polyfill/ie11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Toggle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isOn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsOn&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Toggle&lt;/span&gt; &lt;span class="na"&gt;isOn&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isOn&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setIsOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isOn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now we're handling state &lt;em&gt;outside&lt;/em&gt; of the component.  This means we can change the toggle state anywhere by simply calling &lt;code&gt;setIsOn(!isOn)&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tests
&lt;/h1&gt;

&lt;p&gt;We're ready to publish our package, however let's make sure we have a functioning test first.  We want people to contribute to your project and we don't want to test the functionality in our sandbox every time a new PR is opened.&lt;/p&gt;

&lt;p&gt;Let's rename the &lt;code&gt;blah.test.tsx&lt;/code&gt; file to &lt;code&gt;toggle.test.tsx&lt;/code&gt; and update our &lt;code&gt;react-dom&lt;/code&gt; render method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/tests/blah.test.tsx -&amp;gt; src/tests/toggle.test.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Toggle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;it&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renders without crashing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Toggle&lt;/span&gt; &lt;span class="na"&gt;isOn&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;,&lt;/span&gt; &lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unmountComponentAtNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order for Jest to be able to read CSS files, we'll need to install a package to allow us to mock these files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; identity-obj-proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then edit our package.json to reflect this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// package.json
...
  "jest": {
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "&amp;lt;rootDir&amp;gt;/__mocks__/fileMock.js",
      "\\.(css|less|scss|sass)$": "identity-obj-proxy"
    }
  },
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See &lt;a href="https://jestjs.io/docs/en/webpack#mocking-css-modules" rel="noopener noreferrer"&gt;Jest docs&lt;/a&gt; for more on why this is necessary.  We should have a functioning test now, from your root level directory:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Huzzah!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd7ax7zq70b3vjmwps0wp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd7ax7zq70b3vjmwps0wp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only problem is that this is just testing that the component mounts and doesn't break the app doing so.  What we really want to test is that the toggle functionality and &lt;code&gt;isOn&lt;/code&gt; prop works.&lt;/p&gt;

&lt;p&gt;We can use &lt;a href="https://testing-library.com/docs/react-testing-library/intro" rel="noopener noreferrer"&gt;react-testing-library&lt;/a&gt; to test our component prop functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @testing-library/react @testing-library/jest-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's update our test file to use some of these new testing methods.  We'll be using the &lt;code&gt;render&lt;/code&gt; and &lt;code&gt;fireEvent&lt;/code&gt; methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test/toggle.test.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fireEvent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Toggle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Should render the toggle and be clickable between states&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// mock onChange function&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rerender&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Toggle&lt;/span&gt; &lt;span class="na"&gt;isOn&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// checkbox and parent label components&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Toggle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Toggle-label&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// isOn=false should mean it's unchecked&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;checkbox&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Clicking from off -&amp;gt; on&lt;/span&gt;
  &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// isOn=true should mean it's checked&lt;/span&gt;
  &lt;span class="nf"&gt;rerender&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Toggle&lt;/span&gt; &lt;span class="na"&gt;isOn&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;checkbox&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Clicking from on -&amp;gt; off&lt;/span&gt;
  &lt;span class="nx"&gt;fireEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveBeenCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this is a bit confusing or if you're unfamiliar with react-testing-library, that's okay.  All we're really doing here is rendering the component and making sure &lt;code&gt;isOn&lt;/code&gt; reflects a checked state and that our &lt;code&gt;handleChange&lt;/code&gt; function is called every time on click.&lt;/p&gt;

&lt;p&gt;Double check that it still works:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Publish
&lt;/h1&gt;

&lt;p&gt;You'll want to make sure you update the version, author, and name of your package.  The name should be unique and not taken in the NPM registry.  There are three fields you need to change in your package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; "author": "Frodo Baggins",
 "name: "frodo-toggle",
 "version": "1.0.0",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last step is to publish now!&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you get an error, it's likely that you either need to a) login again via &lt;code&gt;npm login&lt;/code&gt; or b) change the package name to be unique.  If you want to see if the package name is available, try searching for it in the &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm registry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Congratulations, you are now a Typescript package author. 😎&lt;/p&gt;

&lt;p&gt;Anyone can now install your package from the command line by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i your-toggle-lib &lt;span class="c"&gt;# replace this with your package name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Next Steps
&lt;/h1&gt;

&lt;p&gt;There are a few things you could do to make this package better from here.  If you're planning on allowing outside contributors you may want to tweak the default &lt;a href="https://docs.github.com/en/actions/getting-started-with-github-actions/about-github-actions" rel="noopener noreferrer"&gt;Github action&lt;/a&gt; that comes with TSDX to run your test suite on new PRs.  This will make sure that outside contributors are not merging in broken changes.&lt;/p&gt;

&lt;p&gt;Other possible next steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add props to change the color and add labels to the toggle button.
&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;size&lt;/code&gt; prop with "small", "medium", and "large" options.&lt;/li&gt;
&lt;li&gt;Add different transitions based on a prop.&lt;/li&gt;
&lt;li&gt;Add &lt;a href="https://styled-components.com/" rel="noopener noreferrer"&gt;styled-components&lt;/a&gt; instead of css&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The world is your oyster!&lt;/p&gt;

&lt;p&gt;Configuration is the most painful part of any project, but libraries like TSDX and create-react-app are amazing at lowering the barrier of entry for newcomers and lazy people (like me).  No one likes spending a day fighting with configuration files.  Hopefully this guide gives you a bit more confidence that you can write your own packages.  I look forward to seeing your projects on Github and npm!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Why I Stopped Using Redux</title>
      <dc:creator>Gabriel Abud</dc:creator>
      <pubDate>Mon, 06 Jul 2020 21:00:11 +0000</pubDate>
      <link>https://dev.to/g_abud/why-i-quit-redux-1knl</link>
      <guid>https://dev.to/g_abud/why-i-quit-redux-1knl</guid>
      <description>&lt;p&gt;&lt;a href="https://redux.js.org/"&gt;Redux&lt;/a&gt; was a revolutionary technology in the React ecosystem.  It enabled us to have a global store with &lt;a href="https://medium.com/dailyjs/the-state-of-immutability-169d2cd11310"&gt;immutable data &lt;/a&gt; and fixed the issue of &lt;a href="https://kentcdodds.com/blog/prop-drilling"&gt;prop-drilling&lt;/a&gt; in our component tree.  For sharing immutable data across an application, it continues to be an excellent tool that scales really well.&lt;/p&gt;

&lt;p&gt;But why do we need a global store in the first place?  Are our frontend applications really that complex or are we trying to do too much with Redux?&lt;/p&gt;

&lt;h1&gt;
  
  
  The Problem with Single Page Applications
&lt;/h1&gt;

&lt;p&gt;The advent of Single Page Applications (SPAs) such as React, brought about a lot of changes to how we develop web applications.  Separating our backend from our frontend code allowed us to specialize and separate out concerns.  It also introduced a lot of complexity, namely around state.&lt;/p&gt;

&lt;p&gt;Fetching data asynchronously now meant that the data had to live in two places: the frontend and the backend.  We have to think about how best to store that data globally so it's available to all of our components, while maintaining a cache of the data to reduce network latency.  A big part of frontend development now becomes burdened with how to maintain our global store without suffering from state bugs, &lt;a href="https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape#normalizing-state-shape"&gt;data denormalization&lt;/a&gt;, and stale data.&lt;/p&gt;

&lt;h1&gt;
  
  
  Redux is not a Cache
&lt;/h1&gt;

&lt;p&gt;The main problem most of us get into when using Redux and similar state management libraries is that we treat it as a cache for our backend state.  We fetch data, add it to our store with a reducer/action, and refetch it periodically to make sure it's up to date.  We are making Redux do too much and using it as a catch-all solution to our problems.&lt;/p&gt;

&lt;p&gt;One important thing to remember is that our frontend and backend state are never really in sync, at best we can create a mirage that they are.  This is one of the downsides of the &lt;a href="https://en.wikipedia.org/wiki/Client%E2%80%93server_model"&gt;client-server model&lt;/a&gt; and why we need a cache in the first place.  Caching and maintaining state in sync is immensely complex however, so we shouldn't be recreating this backend state from the ground up like &lt;a href="https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape#designing-a-normalized-state"&gt;Redux encourages us to&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The line between backend and frontend responsibility quickly becomes blurred when we start to recreate our database on the frontend.  As frontend developers, we shouldn't need to have a thorough knowledge of &lt;a href="https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape#relationships-and-tables"&gt;tables and their relationships&lt;/a&gt; in order to create a simple UI.  Nor should we have to know &lt;a href="https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape#normalizing-nested-data"&gt;how best to normalize our data&lt;/a&gt;. That responsibility should fall on the people designing the tables themselves - the backend developers.  Backend developers can then provide an abstraction for the frontend developers in the form of a documented API.&lt;/p&gt;

&lt;p&gt;There are now a myriad of libraries (&lt;a href="https://github.com/redux-observable/redux-observable"&gt;redux-observable&lt;/a&gt;, &lt;a href="https://redux-saga.js.org"&gt;redux-saga&lt;/a&gt;, and &lt;a href="https://github.com/reduxjs/redux-thunk"&gt;redux-thunk&lt;/a&gt; to name a few) built around Redux to help us manage data from the backend, each adding a layer of complexity to an already boilerplate-heavy library.  I believe most of these miss the mark.  Sometimes we need to take a step back before taking a step forward.&lt;/p&gt;

&lt;p&gt;What if we stop trying to manage our backend state in our frontend code and instead treat it like a cache that just needs to be updated periodically?  By treating our frontends like simple display layers that read from a cache, our code becomes significantly easier to work with and more accessible to pure frontend developers.  We get all of the benefits of separating out concerns without most of the downsides of building SPAs.&lt;/p&gt;

&lt;h1&gt;
  
  
  A Simpler Approach to Backend State
&lt;/h1&gt;

&lt;p&gt;There are a couple of libraries that I believe are a huge improvement over using Redux (or similar state management library) for storing backend state.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Query
&lt;/h2&gt;

&lt;p&gt;I've been using &lt;a href="https://github.com/tannerlinsley/react-query"&gt;React Query&lt;/a&gt; for a few months in most of my personal and work projects.  It's a library with a very simple API and a couple of hooks to manage queries (fetching data) and mutations (changing data). &lt;br&gt;
 Since using React Query, not only am I more productive but I end up writing 10x less boilerplate code than I would have with Redux.  I find it easier to focus on the UI/UX of my frontend applications without having to keep the whole backend state in my head.&lt;/p&gt;

&lt;p&gt;To compare this library to Redux, it helps to see an example of the two methods in code.  I've implemented a simple TODO list fetched from the server with both methods, using vanilla JS, &lt;a href="https://reactjs.org/docs/hooks-intro.html"&gt;React Hooks&lt;/a&gt;, and &lt;a href="https://github.com/axios/axios"&gt;axios&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;First, the Redux implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-redux&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SET_TODOS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SET_TODOS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rootReducer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="na"&gt;SET_TODOS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/todos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SET_TODOS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;fetchPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this doesn't even begin to handle refetching, caching, and invalidation.  This simply loads the data and stores it in your global store on load.&lt;/p&gt;

&lt;p&gt;Here's the same example implemented with React Query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchTodos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/todos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchTodos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default this examples includes data refetching, caching, and stale invalidation with &lt;a href="https://react-query.tanstack.com/docs/guides/important-defaults"&gt;pretty sensible defaults&lt;/a&gt;.  You can set the caching configuration at the global level and then forget about it - in general it will do what you expect.  For more on how this works under the hood, check out the &lt;a href="https://react-query.tanstack.com/docs/overview"&gt;React Query docs&lt;/a&gt;.  There are a ton of configuration options available to you, this only begins to scratch the surface.&lt;/p&gt;

&lt;p&gt;Anywhere you need this data, you can now use the &lt;a href="https://react-query.tanstack.com/docs/guides/queries"&gt;useQuery hook&lt;/a&gt; with the unique key you set (in this case &lt;code&gt;"todos"&lt;/code&gt;) and the async call to use to fetch the data.  As long as the function is asynchronous, the implementation doesn't matter - you could just as easily use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch"&gt;Fetch API&lt;/a&gt; instead of Axios. &lt;/p&gt;

&lt;p&gt;For &lt;em&gt;changing&lt;/em&gt; our backend state, React Query provides the &lt;a href="https://react-query.tanstack.com/docs/guides/mutations"&gt;useMutation hook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've also written a curated list of React Query resources that you can find &lt;a href="https://github.com/Buuntu/awesome-react-query"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  SWR
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/vercel/swr"&gt;SWR&lt;/a&gt; is conceptually almost identical to React Query.  React Query and SWR were developed around the same time and both influenced each other in positive ways.  There is also a thorough comparison between these two libraries in the &lt;a href="https://react-query.tanstack.com/docs/comparison"&gt;react-query docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Like React Query, SWR also has &lt;a href="https://swr.vercel.app/"&gt;really readable documentation&lt;/a&gt;.  For the most part, you can't go wrong with either library.  Regardless of what ends up becoming the norm in the near future, it will be much easier to refactor from that than the equivalent Redux mess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apollo Client
&lt;/h2&gt;

&lt;p&gt;SWR and React Query focus on REST APIs, but if you need something like this for GraphQL the leading contender is &lt;a href="https://www.apollographql.com/docs/react/"&gt;Apollo Client&lt;/a&gt;.  You'll be pleased to learn that the syntax is almost identical to React Query.&lt;/p&gt;

&lt;h2&gt;
  
  
  What About Frontend State?
&lt;/h2&gt;

&lt;p&gt;Once you start using one of these libraries, you will find that on the vast majority of projects, Redux is overkill.  When the data fetching/caching part of your app is taken care of, there is very little global state for you to handle on the frontend.  What little amount is left can be handled using &lt;a href="https://reactjs.org/docs/context.html"&gt;Context&lt;/a&gt; or &lt;a href="https://blog.bitsrc.io/build-our-own-react-redux-using-usereducer-and-usecontext-hooks-a5574b526475"&gt;useContext + useReducer&lt;/a&gt; to make your own pseudo-Redux.&lt;/p&gt;

&lt;p&gt;Or better yet, use React's built in state for your simple frontend state.  There is nothing inherently wrong with that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// clean, beautiful, and simple&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's embrace the separation of backend from frontend more fully instead of remaining in this ambiguous in-between state.  These up and coming libraries represent a shift in how we manage state in single page applications and are a big step in the right direction.  I'm excited to see where they lead the React community.&lt;/p&gt;

</description>
      <category>redux</category>
      <category>react</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Git Concepts I Wish I Knew Years Ago</title>
      <dc:creator>Gabriel Abud</dc:creator>
      <pubDate>Mon, 29 Jun 2020 17:53:40 +0000</pubDate>
      <link>https://dev.to/g_abud/advanced-git-reference-1o9j</link>
      <guid>https://dev.to/g_abud/advanced-git-reference-1o9j</guid>
      <description>&lt;p&gt;The most used technology by developers is not Javascript.&lt;/p&gt;

&lt;p&gt;It's not Python or HTML.&lt;/p&gt;

&lt;p&gt;It hardly even gets mentioned in interviews or listed as a pre-requisite for jobs.&lt;/p&gt;

&lt;p&gt;I'm talking about Git and version control of course.&lt;/p&gt;

&lt;p&gt;Most of us get by with learning a &lt;a href="https://git-scm.com/docs/gittutorial" rel="noopener noreferrer"&gt;few git concepts&lt;/a&gt; for far too long.  We learn the minimum to get by working on a small team with a simple &lt;a href="https://www.atlassian.com/git/tutorials/comparing-workflows/feature-branch-workflow" rel="noopener noreferrer"&gt;feature branch workflow&lt;/a&gt;.  If you're anything like me, this will carry you for years into your career.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7p7qe33hhlj5zdi3bj82.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7p7qe33hhlj5zdi3bj82.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's time we revisited Git and how important it is to master in order to advance in our careers.  This guide serves as a reference for what I believe are necessary, yet lesser-known concepts. Mastering Git will make a huge difference in how you manage code and your own day-to-day workflow.  Because Git commands are a bit archaic and hard to remember, this guide will be broken up by concepts and expected behavior instead.&lt;/p&gt;

&lt;p&gt;If you don't have a firm grasp of general Git concepts, like the difference between your working directory, local repository, and remote repository, read &lt;a href="https://dev.to/unseenwizzard/learn-git-concepts-not-commands-4gjc"&gt;this guide&lt;/a&gt; first.  Likewise if you don't have the basic git commands mastered, start with the &lt;a href="https://git-scm.com/docs/gittutorial" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.  This guide is not meant to take you from absolute beginner to professional and assumes you are already somewhat proficient using &lt;code&gt;git&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
Git Commands

&lt;ul&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;Navigation&lt;/li&gt;
&lt;li&gt;Modifications&lt;/li&gt;
&lt;li&gt;Cleanup&lt;/li&gt;
&lt;li&gt;Aliases&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Other Git Tricks

&lt;ul&gt;
&lt;li&gt;Ignoring Files&lt;/li&gt;
&lt;li&gt;Special Files&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Git Workflows

&lt;ul&gt;
&lt;li&gt;Rebase vs Merge&lt;/li&gt;
&lt;li&gt;Remote Repository Settings&lt;/li&gt;
&lt;li&gt;Pull Requests&lt;/li&gt;
&lt;li&gt;Branch Naming&lt;/li&gt;
&lt;li&gt;Commit Messages&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Git Commands
&lt;/h1&gt;

&lt;h2&gt;
  
  
  📋 Logging
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What did I just do?
&lt;/h3&gt;

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

git log
git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="c"&gt;# more succinct output&lt;/span&gt;
git log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="c"&gt;# with a visual graph of branches&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  View your "undo" history
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git reflog


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

&lt;/div&gt;

&lt;p&gt;Because sometimes &lt;code&gt;git log&lt;/code&gt; doesn't cut it, especially for commands that don't show up in your commit history.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reflog&lt;/code&gt; is basically your safety net after running "scary" commands like &lt;code&gt;git rebase&lt;/code&gt;.  You'll be able to see not only the commits you made, but each of the actions that led you there.  See &lt;a href="https://www.atlassian.com/git/tutorials/refs-and-the-reflog" rel="noopener noreferrer"&gt;this Atlassian article&lt;/a&gt; to learn more about how refs work.&lt;/p&gt;

&lt;h3&gt;
  
  
  View your current state + any merge conflicts
&lt;/h3&gt;

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

git status


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

&lt;/div&gt;

&lt;p&gt;While &lt;code&gt;git status&lt;/code&gt; is a pretty basic command we all learn early on, its importance as a learning tool for internalizing git fundamentals bears repeating.  It can also help you navigate through a complicated rebase or merge.&lt;/p&gt;

&lt;h3&gt;
  
  
  See the differences in your staged (or unstaged) changes
&lt;/h3&gt;

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

git diff &lt;span class="nt"&gt;--staged&lt;/span&gt; &lt;span class="c"&gt;# for staged changes&lt;/span&gt;
git diff &lt;span class="c"&gt;# for unstaged changes&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  See the differences between two branches
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git diff branch1..branch2


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  🧭 Navigation
&lt;/h2&gt;
&lt;h3&gt;
  
  
  I want to see what I did before
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git reset &amp;lt;commit-sha&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;This will uncommit and unstage those changes but leave those files in the working directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  I want to switch to another branch
&lt;/h3&gt;

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

git switch branch-name   &lt;span class="c"&gt;# new syntax (as of Git 2.23)&lt;/span&gt;
git checkout branch-name &lt;span class="c"&gt;# old syntax&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;git checkout&lt;/code&gt; can be a bit confusing because it can work on the file &lt;strong&gt;and&lt;/strong&gt; branch level.  As of &lt;a href="https://www.infoq.com/news/2019/08/git-2-23-switch-restore/" rel="noopener noreferrer"&gt;Git 2.23&lt;/a&gt;, we now have &lt;code&gt;git restore&lt;/code&gt; (checkout file) and &lt;code&gt;git switch&lt;/code&gt; (checkout branch), which would be my suggestion if you're just starting out to avoid &lt;code&gt;checkout&lt;/code&gt; confusion.&lt;/p&gt;

&lt;h3&gt;
  
  
  I want to go back to the branch I was on
&lt;/h3&gt;

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

git switch -


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  📝 Modifications
&lt;/h2&gt;
&lt;h3&gt;
  
  
  I dug myself into a rabbit hole, let's start over
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD


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

&lt;/div&gt;

&lt;p&gt;This will reset your local directory to match the latest commit and discard unstaged changes&lt;/p&gt;

&lt;h3&gt;
  
  
  I want to reset a file back to how it was
&lt;/h3&gt;

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

git restore &amp;lt;filename&amp;gt;     &lt;span class="c"&gt;# new syntax (as of Git 2.23)&lt;/span&gt;
git checkout &lt;span class="nt"&gt;--&lt;/span&gt; &amp;lt;filename&amp;gt; &lt;span class="c"&gt;# old syntax&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  I want to undo the last commit and rewrite history
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD~1


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  I want to rewind back n commits
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD~n        &lt;span class="c"&gt;# n is the last n commits&lt;/span&gt;
git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; &amp;lt;commit-sha&amp;gt;  &lt;span class="c"&gt;# or to a specific commit&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;There is an important distinction between soft, mixed, and hard resets.  Basically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;--soft&lt;/code&gt;: Uncommit changes but leave those changes staged&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--mixed&lt;/code&gt; (the default): Uncommit and unstage changes, but changes are left in the working directory &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--hard&lt;/code&gt;: Uncommit, unstage, and delete changes&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  I've rewritten history and now want to push those changes to the remote repository
&lt;/h3&gt;

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

git push &lt;span class="nt"&gt;-f&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This is necessary anytime your local and remote repository diverge.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;WARNING&lt;/em&gt;: Force pushing should be done with &lt;strong&gt;great care&lt;/strong&gt;.  In general, on shared branches you should avoid doing any force pushes. Limit force pushing to your own branches, before opening a pull request, so that you don't inadvertently mess up your teammates' git history.&lt;/p&gt;

&lt;h3&gt;
  
  
  I want to add a few more changes to the last commit
&lt;/h3&gt;

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

git commit &lt;span class="nt"&gt;--amend&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  I want to rewrite a bunch of commits locally
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;commit &lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;# where the commit hash is the one *before* all the changes you want to make&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This will open up an interactive prompt where you can select which commits to keep, squash, or delete.  You can also change commit messages here.  This is very useful when cleaning up typo or linting commits, for example.&lt;/p&gt;

&lt;p&gt;I found rebasing to be one of the more confusing topics when learning Git in depth.  See the section on rebasing for more.&lt;/p&gt;

&lt;h3&gt;
  
  
  This rebase is a mess, let's scrap it
&lt;/h3&gt;

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

git rebase &lt;span class="nt"&gt;--abort&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;You can do this mid rebase.  I often find that a rebase is way more trouble than it's worth, especially when rebasing two branches with a lot of similar changes.  Until the rebase is complete, you can always abort it.&lt;/p&gt;

&lt;h3&gt;
  
  
  I want to bring in a commit from a different branch
&lt;/h3&gt;

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

&lt;span class="c"&gt;# From the branch you want to bring the commit *into*&lt;/span&gt;
git cherry-pick &amp;lt;commit-sha&amp;gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  I want to bring in a specific file from a different branch
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git checkout &amp;lt;branch-name&amp;gt; &amp;lt;file-name&amp;gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  I want to stop tracking a file in version control
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;--cached&lt;/span&gt; &amp;lt;file-name&amp;gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  I need to switch branches but my current state is broken
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git stash &lt;span class="c"&gt;# saves your changes to the top of the stash stack&lt;/span&gt;
git stash save &lt;span class="s2"&gt;"message to go along with changes"&lt;/span&gt;
git stash &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="c"&gt;# stash untracked files as well&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  I want to see what's in my stash
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git stash list


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  I want to bring back something in my stash
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git stash pop &lt;span class="c"&gt;# "pops" the most recent item added to the stash stack&lt;/span&gt;
git stash apply stash@&lt;span class="o"&gt;{&lt;/span&gt;stash_index&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="c"&gt;# apply a given item in the stash (from git stash list)&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  I want to undo a commit without rewriting history
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git revert HEAD &lt;span class="c"&gt;# undo the last commit&lt;/span&gt;
git revert &amp;lt;commit &lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;# for a specific commit&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This will replay the inverse of the commit specified as a new commit, thereby undoing your changes without undoing history.  This is a much safer way to undo a commit on shared branches, where rewriting history has much bigger consequences.&lt;/p&gt;

&lt;h3&gt;
  
  
  I want to find which commit caused a bug
&lt;/h3&gt;

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

git bisect start
git bisect bad           &lt;span class="c"&gt;# Current version is bad&lt;/span&gt;
git bisect good v1.1     &lt;span class="c"&gt;# v1.1 is known to be good&lt;/span&gt;

git &lt;span class="nb"&gt;help &lt;/span&gt;bisect          &lt;span class="c"&gt;# For more&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This one is a bit tricky so see &lt;a href="https://git-scm.com/docs/git-bisect" rel="noopener noreferrer"&gt;the documentation&lt;/a&gt; for more.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧹 Cleanup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Oh my god how do I have so many branches?
&lt;/h3&gt;

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

git branch --no-color --merged | command grep -vE "^(\+|\*|\s*(master|develop|dev)\s*$)" | command xargs -n 1 git branch -d


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

&lt;/div&gt;

&lt;p&gt;This will delete all merged branches that you have locally except for master, developer or dev.  If you have different names for your main and dev branches, you can change the &lt;code&gt;grep&lt;/code&gt; regex accordingly.&lt;/p&gt;

&lt;p&gt;This is a long command to remember, however you can set it to an alias like so:&lt;/p&gt;

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

&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gbda&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'git branch --no-color --merged | command grep -vE "^(\+|\*|\s*(master|develop|dev)\s*$)" | command xargs -n 1 git branch -d'&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;If you use Oh My Zosh this is already done for you. See the section on aliases for more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's garbage collect old branches/detached commits
&lt;/h3&gt;

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

git fetch &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--prune&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This is also a really useful command if you've setup your remote repository to delete branches on merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⌨️ Aliases
&lt;/h2&gt;

&lt;p&gt;Git commands can be long and really hard to remember.  We don't want to type them out each time or spend days memorizing them, so I strongly recommend you make git aliases for them.&lt;/p&gt;

&lt;p&gt;Better yet, install a tool like &lt;a href="https://ohmyz.sh/" rel="noopener noreferrer"&gt;Oh My Zosh&lt;/a&gt; for Z shell (Zsh) and you will get a bunch of the &lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Cheatsheet#git" rel="noopener noreferrer"&gt;most commonly used git commands as aliases&lt;/a&gt; by default + tab completion for these.  I'm lazy about configuring my shell exactly how I want it so I love open source tools like Oh My Zosh that do this for me.  Not to mention it comes with a sweet looking shell.&lt;/p&gt;

&lt;p&gt;Some of my favorites I use almost every day:&lt;/p&gt;

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

gst - git status
gc  - git commit
gaa - git add &lt;span class="nt"&gt;--all&lt;/span&gt;
gco - git checkout
gp  - git push
gl  - git pull
gcb - git checkout &lt;span class="nt"&gt;-b&lt;/span&gt;
gm  - git merge
grb - git rebase
gpsup - git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin &lt;span class="si"&gt;$(&lt;/span&gt;current_branch&lt;span class="si"&gt;)&lt;/span&gt;
gbda  - git branch &lt;span class="nt"&gt;--no-color&lt;/span&gt; &lt;span class="nt"&gt;--merged&lt;/span&gt; | &lt;span class="nb"&gt;command grep&lt;/span&gt; &lt;span class="nt"&gt;-vE&lt;/span&gt; &lt;span class="s2"&gt;"^(&lt;/span&gt;&lt;span class="se"&gt;\+&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\*&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;*(master|develop|dev)&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="nv"&gt;$)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;command &lt;/span&gt;xargs &lt;span class="nt"&gt;-n&lt;/span&gt; 1 git branch &lt;span class="nt"&gt;-d&lt;/span&gt;
gfa - git fetch &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--prune&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;If you forget what these aliases or any others you have set yourself stand for, you can run simply run:&lt;/p&gt;

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

&lt;span class="nb"&gt;alias&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Or to search for a given alias:&lt;/p&gt;

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

&lt;span class="nb"&gt;alias grep&lt;/span&gt; &amp;lt;alias-name&amp;gt;


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

&lt;/div&gt;
&lt;h1&gt;
  
  
  Other Git Tricks
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Ignoring Files
&lt;/h2&gt;

&lt;p&gt;Many files do not belong in version control.  You should utilize your &lt;a href="http://egorsmirnov.me/2015/05/04/global-gitignore-file.html" rel="noopener noreferrer"&gt;global gitignore&lt;/a&gt; for this.  Examples of things that do not belong in version control are &lt;code&gt;node_modules&lt;/code&gt; directories, &lt;code&gt;.vscode&lt;/code&gt; or other IDE files, and Python virtual environments.  &lt;/p&gt;

&lt;p&gt;For any sensitive information, you can use environment files and add these to your local &lt;code&gt;.gitignore&lt;/code&gt; at the root of your project.&lt;/p&gt;
&lt;h2&gt;
  
  
  Special Files
&lt;/h2&gt;

&lt;p&gt;You may need to mark certain files as binary files so that git knows to ignore them and doesn't produce lengthy diffs.  Git has a &lt;code&gt;.gitattributes&lt;/code&gt; file for just this purpose.  In a Javascript project, you may want to add your &lt;code&gt;yarn-lock.json&lt;/code&gt; or &lt;code&gt;package-lock.json&lt;/code&gt; so that Git doesn't try to diff them every time you make a change.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# .gitattributes&lt;/span&gt;
package-lock.json binary


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

&lt;/div&gt;
&lt;h1&gt;
  
  
  Git Workflows
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Rebase vs Merge
&lt;/h2&gt;

&lt;p&gt;Your team may choose to adopt either a rebase or merge workflow.  There are pros and cons to both, and I've seen both be used effectively.  For the most part, unless you &lt;em&gt;really&lt;/em&gt; know what you're doing, you should probably opt for a merge workflow.&lt;/p&gt;

&lt;p&gt;You can still use rebase effectively even when you're primarily using merge to bring in your changes into production.  The most common situation that would call for this, is if you're working on a feature while another developer pulls in a feature into master.  You could certainly use &lt;code&gt;git merge&lt;/code&gt; to bring those changes in, but now you have an extra commit for the simple change your teammate made.  What you really want is to &lt;em&gt;replay&lt;/em&gt; your commits on top of the new master branch.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git rebase master


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

&lt;/div&gt;

&lt;p&gt;This should give you a much cleaner commit history now.&lt;/p&gt;

&lt;p&gt;To explain the difference in depth would take a whole article  (blog post pending), so I suggest you check out &lt;a href="https://www.atlassian.com/git/tutorials/merging-vs-rebasing" rel="noopener noreferrer"&gt;the Atlassian docs&lt;/a&gt;  on the difference instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remote Repository Settings
&lt;/h2&gt;

&lt;p&gt;I am most familiar with Github and Gitlab, however these settings should be supported by most other remote repository managers.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Delete branches on merge
&lt;/h3&gt;

&lt;p&gt;Once things are merged, you should not care about the branch anymore since the history should be reflected on your master/dev branch.  This significantly cleans up the number of branches you have to manage.  It also makes &lt;code&gt;git fetch --all --prune&lt;/code&gt; much more effective in keeping your local repository clean.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Prevent pushes directly to master
&lt;/h3&gt;

&lt;p&gt;Without this, it's a very understandable mistake to accidentally forget you're on master and do a &lt;code&gt;git push&lt;/code&gt;, potentially braking your production build.  Not good.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Require at least one approval before merging
&lt;/h3&gt;

&lt;p&gt;Depending on the size of your team, you may want to require even &lt;em&gt;more&lt;/em&gt; than one approval before merging.  The bare minimum should be one though, even if you're on a team of 2 people.  You don't have to spend hours nit picking every single line, but in general your code should have two sets of eyes on it.  &lt;a href="https://dev.to/g_abud/effective-learning-and-feedback-loops-1110"&gt;Feedback&lt;/a&gt; is key to learning and personal growth.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Require passing CI tests to merge
&lt;/h3&gt;

&lt;p&gt;Broken changes should not be merged into production. Reviewers will not be able to catch broken changes 100% of the time, so automate these checks instead.  Enough said.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull Requests
&lt;/h2&gt;

&lt;p&gt;Keep pull requests small and concise, no more than a couple hundred lines ideally.  Small and frequent pull requests will make the review process faster, lead to more bug-free code, and make your teammates' life easier.  It will also lead to increased productivity and more shared learning.  Make a commitment with your team to spend a certain amount of time reviewing open pull requests, every day.&lt;/p&gt;

&lt;p&gt;We all love reviewing these:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgdcwrvn006gryk0xiox0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgdcwrvn006gryk0xiox0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're working on a feature that will be in a broken state for a while, use &lt;a href="https://www.martinfowler.com/articles/feature-toggles.html" rel="noopener noreferrer"&gt;feature flags&lt;/a&gt; to disable it in production.  This will prevent your feature branch from diverging too much from your dev/master branch and allow you to do more frequent, small pull requests.  The longer you go without merging code in, the harder it will be to do so later.&lt;/p&gt;

&lt;p&gt;Finally, include a detailed description in your pull request, with images and/or gifs if necessary.  If you use a tool like Jira to manage tickets, include the ticket number the pull request addresses.  The more descriptive and visual you make your pull request, the more likely your teammates will want to review it and not drag their feet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Branch Naming
&lt;/h2&gt;

&lt;p&gt;Your team may want to come up with branch naming conventions for easier navigation.  I like to start each branch with the first letter of your first name + last name, followed by a forward slash, and the branch description separated by hyphens.&lt;/p&gt;

&lt;p&gt;This may seem insignificant but with tab completion and tools like grep, this can really facilitate finding and making sense of all the branches you may have.&lt;/p&gt;

&lt;p&gt;For example, when I create a new branch:&lt;/p&gt;

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

git checkout -b gabud/implement-important-feature


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

&lt;/div&gt;

&lt;p&gt;A week later when I forget what I called my branch, I can start typing &lt;code&gt;git checkout gabud&lt;/code&gt;, press TAB, and my Z shell then shows me all of my local branches to choose from without seeing any of my teammates' branches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commit Messages
&lt;/h2&gt;

&lt;p&gt;Language is important.  In general I find it best to not commit things in broken states, and each commit should have a succinct message that explains what the change should do.  Following the official &lt;a href="https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project" rel="noopener noreferrer"&gt;Git recommendation&lt;/a&gt;, I find it best to use the present, imperative sense for commit messages.  Think of each commit message as being a command to the computer/git, which you can add to the end of this sentence:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If this commit were applied, it would...&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An example of a good commit message in the present, imperative sense would then be:&lt;/p&gt;

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

git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add name field to checkout form"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Which now reads: "If this commit were applied, it would add name field to checkout form".  Nice and clear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This is by no means all there is to learn about Git.  I suggest you checkout the &lt;a href="https://git-scm.com/doc" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; and &lt;code&gt;git help&lt;/code&gt; for more.  Don't be afraid to ask for help with Git from your teammates, you'd be surprised to learn that most of your teammates have many of the same questions.&lt;/p&gt;

&lt;p&gt;What about you? Which Git commands or concepts have been the most instrumental in your workflow?&lt;/p&gt;

</description>
      <category>git</category>
      <category>productivity</category>
      <category>github</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Prettier and the Beauty of Opinionated Code Formatters</title>
      <dc:creator>Gabriel Abud</dc:creator>
      <pubDate>Wed, 24 Jun 2020 18:22:36 +0000</pubDate>
      <link>https://dev.to/g_abud/prettier-and-the-beauty-of-opinionated-code-formatters-pfg</link>
      <guid>https://dev.to/g_abud/prettier-and-the-beauty-of-opinionated-code-formatters-pfg</guid>
      <description>&lt;p&gt;I love &lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's probably the single tool that has had the biggest effect on my productivity as a programmer (after Git, maybe).&lt;/p&gt;

&lt;p&gt;For those of you that don't know, Prettier is an opinionated code formatter for Javascript/Typescript, HTML, JSX, and more.  It is lightweight, requires next to no configuration, and automatically formats code for you.  Gone are the days where you spend half of your day arguing with co-workers how to nest HTML, what the correct line length is, or whether strings should have single vs double quotes.&lt;/p&gt;

&lt;p&gt;This is my Prettier configuration:&lt;/p&gt;

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

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;printWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;singleQuote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trailingComma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;es5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Isn't that simple?  My settings are a bit opinionated so you can get by with even less!&lt;/p&gt;

&lt;p&gt;I use VSCode, so I setup all my projects to format on save.  I strongly recommend you do the same if you haven't already.  Any modern IDE should have this capability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy2bep355jozw37iy0im0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy2bep355jozw37iy0im0.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;There is a strange pleasure in seeing your garbled JSX fit perfectly into place on save.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Rise of the Opinionated Formatter
&lt;/h1&gt;

&lt;p&gt;Opinionated formatters are great because they eliminate the ongoing flame war nerds and programmers love to have about code formatting.  While it's good that we care this much about the quality of our code, overall this is a huge waste of time.  Since we started using Prettier on my team, pull request reviews are much more effective and we're no longer having stylistic discussions every. single. week.  &lt;/p&gt;

&lt;p&gt;We need to start valuing our time more and realize these discussions are a waste of time.  While you may be right that God's intention for strings is to use double quotes, &lt;strong&gt;it really doesn't matter&lt;/strong&gt;.  The benefit of using them is already outweighed by the time you've wasted discussing it.  Leave that discussion and mental baggage to the Prettier team, I promise they've already &lt;a href="https://github.com/prettier/prettier/blob/master/CHANGELOG.md" rel="noopener noreferrer"&gt;given plenty of thought&lt;/a&gt; to what the best defaults are.&lt;/p&gt;

&lt;p&gt;Prettier is not the only code formatter out there.  For Python, I use and love &lt;a href="https://pypi.org/project/black/" rel="noopener noreferrer"&gt;Black&lt;/a&gt;.  Check out &lt;a href="https://github.com/rishirdua/awesome-code-formatters" rel="noopener noreferrer"&gt;this Github repo&lt;/a&gt; for alternatives in other languages.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to Enforce Prettier
&lt;/h1&gt;

&lt;p&gt;There are many ways to enforce Prettier on your team besides having everyone set it up in their IDE.  If you are purely a frontend team, you can use &lt;a href="https://prettier.io/docs/en/precommit.html" rel="noopener noreferrer"&gt;husky and lint-staged&lt;/a&gt;.  If you are working on a full-stack or multi-language team, you can use the &lt;a href="https://prettier.io/docs/en/precommit.html#option-3-pre-commithttpsgithubcompre-commitpre-commit" rel="noopener noreferrer"&gt;pre-commit Python package&lt;/a&gt; to run Prettier as a pre-commit hook.  That means that any staged files will be Prettified when you commit using git.&lt;/p&gt;

&lt;h1&gt;
  
  
  Do we need Additional Linting?
&lt;/h1&gt;

&lt;p&gt;In the past, I used &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; heavily in my frontend projects.  Especially with &lt;a href="https://github.com/airbnb/javascript" rel="noopener noreferrer"&gt;Airbnb's configuration&lt;/a&gt;, which tends to be very strict.&lt;/p&gt;

&lt;p&gt;The problem with ESLint is that it's too configurable.  It doesn't solve the stylistic flame war.  It just ends up adding options, which we really need &lt;em&gt;less&lt;/em&gt; of.  As web developers we already suffer from &lt;a href="https://en.wikipedia.org/wiki/Decision_fatigue" rel="noopener noreferrer"&gt;decision fatigue&lt;/a&gt;, having to choose between frameworks, 3rd party libraries, state management, different styling options, REST vs GraphQL, build tools, etc.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An example of ESLint decision fatigue from a real project:&lt;/em&gt;&lt;/p&gt;

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

&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react/no-unescaped-entities&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-restricted-syntax&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-continue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-underscore-dangle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;operator-linebreak&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;implicit-arrow-linebreak&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react/destructuring-assignment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react/no-multi-comp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsx-a11y/click-events-have-key-events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsx-a11y/no-static-element-interactions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react/jsx-one-expression-per-line&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lines-between-class-members&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;always&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;exceptAfterSingleLine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react/no-array-index-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;off&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;ESLint rules are often arbitrarily turned on/off based on people's opinion.  Either that or you need a whole README devoted to why certain rules are enforced and others are not.  Every time you bring on a new developer you are then opening up these decisions to question.  This is too much unnecessary mental drain on everyone.&lt;/p&gt;

&lt;p&gt;Most of what ESLint enforces is not automatically fixable, unlike Prettier.  This makes it clunky to run in CI or as a pre-commit hook.  It requires a developer to go and try to fix it themselves, creating additional manual work.  Fixing linting issues is not the fun part of coding.&lt;/p&gt;

&lt;p&gt;I still think ESLint has some uses, however with Prettier I think those are pretty minimal.  My configuration now basically just extends &lt;a href="https://github.com/facebook/create-react-app/tree/master/packages/eslint-config-react-app" rel="noopener noreferrer"&gt;eslint-config-react-app&lt;/a&gt; (used by &lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;create-react-app&lt;/a&gt;) and &lt;a href="https://github.com/prettier/eslint-plugin-prettier" rel="noopener noreferrer"&gt;eslint-prettier&lt;/a&gt; (to avoid conflicting Prettier and ESLint rules), and I don't touch any extra rules.  I could see myself getting rid of it eventually as Prettier matures.&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;.eslintrc.js&lt;/code&gt; now looks like this:&lt;/p&gt;

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

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plugin:prettier/recommended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Simplicity is underrated.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What about you?
&lt;/h1&gt;

&lt;p&gt;Have you found Prettier or opinionated formatters to be as useful for yourself and your team?  Do you think ESLint (or additional linting) is necessary and conducive to productivity?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Effective Learning and Feedback Loops</title>
      <dc:creator>Gabriel Abud</dc:creator>
      <pubDate>Wed, 10 Jun 2020 17:52:59 +0000</pubDate>
      <link>https://dev.to/g_abud/effective-learning-and-feedback-loops-1110</link>
      <guid>https://dev.to/g_abud/effective-learning-and-feedback-loops-1110</guid>
      <description>&lt;p&gt;I follow a lot of tech people on Twitter that like to give advice to prospective developers on how to get started.  Most of it looks like this:&lt;/p&gt;

&lt;p&gt;"Start by learning HTML, CSS, vanilla JS, and how HTTP works"&lt;/p&gt;

&lt;p&gt;"Get into data science by learning Python fundamentals, statistics, and higher-level calculus"&lt;/p&gt;

&lt;p&gt;"Start with jQuery before learning React"&lt;/p&gt;

&lt;p&gt;I used to think like this too, in fact half of my bookshelf right now consists of old discarded programming language books that I hardly opened.  Like in any skilled profession, there is a lot to learn and not much guidance on where to start.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Effective Learning?
&lt;/h1&gt;

&lt;p&gt;We've all heard the phrase, "it takes 10,000 hours to become an expert at something".  Some people with natural talent will become experts in much less time, however there is no getting around the matter that becoming good at anything takes a &lt;strong&gt;significant&lt;/strong&gt; amount of time.  It's why medical school takes 10 years (or less if you live outside of the US).  It's why athletes like Michael Phelps at their peak  would train ~6 hours a day, 5-6 days a week.  It's why Mozart never stopped practicing the piano.&lt;/p&gt;

&lt;p&gt;I think the focus of what to learn is missing the point.  It's not what you should start learning, it's what makes you the most excited to continue.  If it takes such a significant amount of time to get really good at something, it doesn't really matter what you start with &lt;em&gt;as long as it motivates you&lt;/em&gt;.  This means you need to create good feedback loops around your learning.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Feedback Loop
&lt;/h1&gt;

&lt;p&gt;One of the reasons Silicon Valley has become so successful is because they've embraced this notion of experimentation.  Facebook's old motto was "move fast and break things".  While this is a problematic motto for other reasons, there is no denying that Facebook has become very successful as a company, and I think this motto gives us a glimpse as to why.  Quick experimentation leads to quick feedback, which leads to more experimentation, and so on.  Examples of companies with quick iteration loops abound in Silicon Valley - Google, Uber, Tesla, Twitter, and Apple are always churning out new products and ideas.&lt;/p&gt;

&lt;p&gt;This is also the concept around &lt;a href="https://en.wikipedia.org/wiki/Agile_software_development"&gt;Agile programming&lt;/a&gt;.  Quick iteration cycles lead to quick feedback, which in turn lead to quick products.&lt;/p&gt;

&lt;p&gt;To learn anything well, you need to create short feedback loops between your practice and the result.  This feedback loop motivates you to continue practicing and learning.  If Michael Jordan had spent all of his teenage years shooting free throws without constantly playing with others, he would have given up in frustration long before joining the NBA.&lt;/p&gt;

&lt;p&gt;Fundamentally this is a biochemical pathway in your brain that you have to wire.  You perform an activity which causes some result, which creates a neurochemical response in your brain, which makes you look forward to doing that activity again.  For Michael Jordan the response is scoring a basket.  For musicians it's hearing beautiful music.  For programmers it's creating intelligent software.  It's also why social media is so addicting, but I digress.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nfka-F_A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ig9lqurge3d47xycncjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nfka-F_A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ig9lqurge3d47xycncjo.png" alt="Feedback Loop" width="600" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Examples of Feedback Loops
&lt;/h1&gt;

&lt;p&gt;Feedback can come in a lot of different ways.  We are social creatures however, so the most effective form of feedback is from others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning a New Language
&lt;/h2&gt;

&lt;p&gt;A lot of the same concepts in programming also apply to learning a new language.  Rather than starting by learning the gender tenses, verb conjugations, and past/present/future forms of verbs, start with something much simpler that gives you instant feedback.  &lt;/p&gt;

&lt;p&gt;The reason that people who fully immerse themselves in a language learn an order of magnitude faster is because their feedback loops are much shorter.  As someone who is bilingual and has successfully (and not so successfully) learned other languages, my advice would be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Learn some of the basic question words (how, where, why, what, when, who).  Questions are some of the easiest ways to start a conversation with strangers and conversations give you instant feedback.  If you can learn how to order at a restaurant, ask where the bathroom is, and ask for directions, then you can basically visit any country on your own.&lt;/li&gt;
&lt;li&gt;Go to meetups where you can talk to others who are learning without feeling embarrassed.  Talking to other people is one of the best ways to get feedback but you won't do it if you're ashamed to make mistakes.&lt;/li&gt;
&lt;li&gt;Watch Netflix shows, listen to music in that language, or watch Youtube tutorials in that language.&lt;/li&gt;
&lt;li&gt;If within your financial means, take a vacation to a country that speaks that language and use the few words you've learned to start conversations.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Learning to Program
&lt;/h2&gt;

&lt;p&gt;In programming, feedback may come from seeing your program do something cool.  It doesn't have to be feedback from others, it can be from your computer.  Although as social beings feedback from others will always be more motivating.&lt;/p&gt;

&lt;p&gt;When you make a simple Hello World application, seeing the output in your terminal is feedback.  When you make a change to a React application and see your website instantly reload, that is feedback.  When you get a job at a company because you learned and mastered the most in demand technologies - that is feedback.&lt;/p&gt;

&lt;p&gt;So what is the path of least resistance to getting some of this feedback?  Build things.  It doesn't matter what, don't suffer from &lt;a href="https://en.wikipedia.org/wiki/Analysis_paralysis"&gt;analysis paralysis&lt;/a&gt;.  If you like following tutorials on building TODO apps, do that.  If you like thinking about the stock market, build an app that helps you track it.  If you like playing chess, build a chess app.  Build whatever motivates you and will give you instant feedback.&lt;/p&gt;

&lt;p&gt;Another great way to get quick feedback is to &lt;em&gt;write tests&lt;/em&gt;.  Tests serve a myriad of purposes (see &lt;a href="https://dev.to/g_abud/on-testing-2k0i"&gt;Why do we Test?&lt;/a&gt;), but one of the biggest benefits is that you get near instant feedback in the form of passing or failing tests.  This significantly shortens your feedback loop and leads to quicker development, and therefore quicker learning.&lt;/p&gt;

&lt;p&gt;As you become more advanced, you will be able to build more interesting applications and still maintain this quick feedback loop.  But you don't need to start with that, you're not going to make something used by thousands of people on the first try.  If you hold yourself to such high standards you will also struggle, not receive any feedback, and ultimately give up.&lt;/p&gt;

&lt;h1&gt;
  
  
  My Advice
&lt;/h1&gt;

&lt;p&gt;Don't code in a black box.  If you write code professionally already, you can institute better practices to form shorter feedback loops.  Write lots of quick, easy to maintain tests.  Open short, frequent pull requests and be sure to institute good code review practices.  If you work on a team, every pull request should be reviewed by at least one other developer.  If you don't code professionally, make pull requests to open source projects.  It's fine if these are corrections to documentation or better comments on code to start - that is still feedback.  &lt;/p&gt;

&lt;p&gt;And host all your projects on Github with good READMEs for others.  You'll be surprised how often a project that you think is useless will get interest from others.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Learn
&lt;/h2&gt;

&lt;p&gt;Rather than learning 10 foundational things before ever getting started, my advice is to learn in such a way that minimizes your feedback loop.  In software, here are some ideas of the path of least resistance that minimize your feedback loop.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Learn React to build a simple application.  It can be anything.  Host it on Github and share it with others with a one-click deploy service like &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt; or &lt;a href="https://aws.amazon.com/amplify/"&gt;AWS Amplify&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Learn Data Science by learning Pandas and applying it to automating mundane spreadsheet tasks at work.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Learn Python by building a functioning website using Django and Django plugins for authentication.  Deploy this using &lt;a href="https://www.heroku.com/free"&gt;Heroku's free tier&lt;/a&gt; and a &lt;a href="https://devcenter.heroku.com/articles/deploying-python"&gt;Django config&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point is not the languages (you can swap out React for Vue or Python for Rust if that's what interests you), the point is that these are some of the easiest ways to build appealing applications.  React, Django, and Python are also among the most employable skills in web development right now.  Here's the latest &lt;a href="https://insights.stackoverflow.com/survey/2020"&gt;Stackoverflow developer survey&lt;/a&gt; if you don't believe me.  Receiving a job offer is a very strong form of feedback.  You could certainly learn the fundamentals first and build an application with pure HTML and CSS, hosted on your own server on Digital Ocean.  You will certainly learn a lot, but the feedback you get from building that (an ugly website that looks like it's from the 90's) will not encourage you to continue learning.  I also haven't yet seen a job posting that only asks for ninja level HTML/CSS skills.&lt;/p&gt;

&lt;p&gt;Whether it's from other people, from seeing your computer do something that you told it to, or from making some mundane task at work easier, getting feedback is key.  Once you gain a certain level of proficiency, your feedback loop will be much shorter and your learning will grow exponentially.  The key is to get started!&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Why do we Test?</title>
      <dc:creator>Gabriel Abud</dc:creator>
      <pubDate>Sat, 06 Jun 2020 19:21:27 +0000</pubDate>
      <link>https://dev.to/g_abud/on-testing-2k0i</link>
      <guid>https://dev.to/g_abud/on-testing-2k0i</guid>
      <description>&lt;p&gt;Why do we test?  &lt;/p&gt;

&lt;p&gt;As I write tests way past the work day and fight with Jest, mocks, and React components, I find myself ruminating over this question.&lt;/p&gt;

&lt;p&gt;What is the point?  Is it to meet some arbitrary metric (90% or 100% test coverage) placed on by managers or senior engineers?  Is it for the user, so they have a better user experience and less bugs?  Is it for yourself, to feed some narcissistic tendencies and grandiose ideas that you're the best programmer in the world?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Am I the only one that gets a dopamine rush from these little green dots?&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftfp9rdf5yh6n43zh2ki5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftfp9rdf5yh6n43zh2ki5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ultimately the most important metric for a business is how much money is saved by writing tests.  But how many of us, as engineers, really have a good understanding of this?&lt;/p&gt;

&lt;p&gt;Developers don't care about this.  Not only that, they are so far removed from the money making aspect of a business that it's impossible for them to have a good understanding of this.  A project manager may have a better understanding, but they're not the ones writing the tests.  Nor will they have a good enough understanding of a codebase to be able to tell a developer what to test.  The people in a business that understand the true cost of things don't understand the software and how it's written.  This is one of the conundrums of &lt;a href="https://en.wikipedia.org/wiki/Division_of_labour" rel="noopener noreferrer"&gt;labor specialization&lt;/a&gt;.  We become experts in our domain but in doing so miss the bigger picture.&lt;/p&gt;

&lt;p&gt;So as narrow-minded engineers, we need a better reason than "to save money".  Something that we can understand and relate to, while not being too constrictive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We should test to save developer time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hear me out.  Developer time is something we have a good understanding of (some of you may scoff at this, I know).  Developers understand what features are likely to break and how long things will take to implement.  Your team's time is not free, so in most cases it is pretty strongly correlated with saving your company money anyway.  Testing, in essence, is an investment in your team's future development experience.  Saving developer time is ultimately the principle around DRY programming, extreme programming (XP), and SLURP programming.  Okay I made that last one up, there are too many stupid programming acronyms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0lkfya38rrykgj3qmos.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0lkfya38rrykgj3qmos.png" alt="Is it worth your time?"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our own time also holds up better as a metric in different situations and company types.  Facebook and Google will have drastically different use cases for tests than a small startup getting off the ground.  A breaking feature in production for &lt;a href="http://www.facebook.com" rel="noopener noreferrer"&gt;www.facebook.com&lt;/a&gt; is likely to set off a wave of alarm bells that results in a lot of work for developers (aka $$$).  End to end tests for a product that is used by millions of people is therefore much more crucial than one used internally by a handful of employees.&lt;/p&gt;

&lt;p&gt;But how does prioritizing developer time help us to actually write better tests?&lt;/p&gt;

&lt;p&gt;Let's go over the different kind of tests and why this way of thinking can help you:&lt;/p&gt;
&lt;h1&gt;
  
  
  1. Unit Tests
&lt;/h1&gt;

&lt;p&gt;These should be the quickest to write and should give us assurance that the individual pieces of our system work as we intended.  Ultimately these should run quickly, test your own code (not 3rd party libraries), and serve as documentation for future developers.  They save developer time by facilitating refactoring and helping onboard new team members.  When an integration test inevitably fails, it is likely that a unit test can tell you exactly where and why it failed.  Writing around a test interface also promotes good code practices, like using &lt;a href="https://www.freecodecamp.org/news/what-is-a-pure-function-in-javascript-acb887375dfe/" rel="noopener noreferrer"&gt;pure functions&lt;/a&gt; and &lt;a href="https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/" rel="noopener noreferrer"&gt;dependency injection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Unit tests should be quick enough so that you can use tests to drive development&lt;/em&gt; (see &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development" rel="noopener noreferrer"&gt;TDD&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;While you can and should have unit tests for both the frontend and backend, I believe they have most value in your backend business logic.&lt;/p&gt;
&lt;h1&gt;
  
  
  2. Integration Tests
&lt;/h1&gt;

&lt;p&gt;These test how things interact within your system.  Integration tests save us time by preventing common use cases from breaking as we refactor.  I tend to think of these as more frontend-leaning tests, although they can also be on the backend.  They are also much quicker than manually clicking through multi-step forms, assuming they are well written.  Integration tests may still use mocks and give us more assurance (per unit of time spent writing them) than unit tests that our system works as the user expects.&lt;/p&gt;
&lt;h1&gt;
  
  
  3. End to end tests
&lt;/h1&gt;

&lt;p&gt;These test how your system interacts as a whole.  A true end to end test does not have any mocks and is running through your software in a way that real users might use it.  These have the most value but are also the most complicated to run and take the most time.  End to end tests save developer time by preventing after hours calls about how billing is down for the entire company.  Maybe your TLS certificate expired or your Single Sign-On provider is misconfigured.  Dammit John I told you not to touch those settings.&lt;/p&gt;
&lt;h1&gt;
  
  
  Are there any bad tests?
&lt;/h1&gt;

&lt;p&gt;This is not to say that &lt;strong&gt;all&lt;/strong&gt; tests are good.  You have to keep an eye out for bad tests too, the ones that take up developer time.&lt;/p&gt;

&lt;p&gt;Examples of this are tightly coupled tests or ones that care too much about the implementation details.  You should constantly be asking yourself, what am I trying to achieve with this test?  Am I testing new business logic, which is prone to human error and refactors, or am I testing how an existing library works?  You don't need to test React, Flask, or Django, there are already thousands of developers who have done that job for you.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-762283869458620416-542" src="https://platform.twitter.com/embed/Tweet.html?id=762283869458620416"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-762283869458620416-542');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=762283869458620416&amp;amp;theme=dark"
  }



&lt;br&gt;
&lt;em&gt;"Because Dan Abramov said so" is not a good testing philosophy&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If a test is going to take you a couple of days to write, is already mostly covered by simpler tests, and does not cover realistic use cases, it's a good sign that it may not be necessary.&lt;/p&gt;

&lt;p&gt;Likewise, a test that takes several seconds to run because you didn't mock some expensive 3rd party function is going to cost time for every developer.  It may make sense for you as a sole developer to write this test, but now multiply the seconds that test takes x the number of times each developer runs the test suite in a day x the number of developers at your company.  It quickly adds up.&lt;/p&gt;

&lt;p&gt;If your tests are written in such a way that every little change to the codebase requires refactoring a test (or more than one) needlessly, it is definitely not a time saver.  This is my problem with &lt;a href="https://jestjs.io/docs/en/snapshot-testing" rel="noopener noreferrer"&gt;Snapshot testing&lt;/a&gt;.  These kind of tests make us feel "safe" but they are not actually saving any amount of time or making our code any less error prone.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-807626710350839808-144" src="https://platform.twitter.com/embed/Tweet.html?id=807626710350839808"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-807626710350839808-144');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=807626710350839808&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I think what Guillermo is getting at is that tests can get messy and a few well thought out ones will give you most of your results.  Tests, like software and many other fields tend to follow the &lt;a href="https://en.wikipedia.org/wiki/Pareto_principle" rel="noopener noreferrer"&gt;80/20 principle&lt;/a&gt;.  20% of tests will end up giving you 80% of the results.  Don't just mindlessly write tests for the sake of writing them, to reach some arbitrary coverage number, or because you saw an image of pyramid that tells you how important unit tests are.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq92ynrg3dk8qax25jk4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq92ynrg3dk8qax25jk4b.png" alt="Testing Pyramid"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Take these diagrams with a grain of salt&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Instead of asking fellow engineers to always write tests, make sure they understand &lt;strong&gt;why&lt;/strong&gt; they're writing them.  100% code coverage does not literally mean it is 100% safe, you could have a bad test that will never occur in reality and is considered to have 100% coverage.  From personal experience, not enough time is spent talking about what good tests look like.&lt;/p&gt;

&lt;p&gt;So besides awareness, how do we use this concept to better our development?  Through consistent reviews and reflection on the tests we write.  Is a piece of code creating a disproportionate amount of maintenance work for you?  Maybe it's time to refactor and write better tests for it.&lt;/p&gt;

&lt;p&gt;Rather than focusing on unhelpful metrics or rigid rules, testing should be treated as a continual learning/betterment process.  Tests should have the necessary attention paid to them and not be treated as second class citizens.  Everyone should spend time refactoring and reviewing them, discarding ones that are not testing essential pieces of your software, and improving slow ones.  Scrap your next stand-up and instead have a test-up, it'll be a much more productive use of developer time.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>unit</category>
      <category>python</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
