<?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>Forem: MapleLeaf</title>
    <description>The latest articles on Forem by MapleLeaf (@mapleleaf).</description>
    <link>https://forem.com/mapleleaf</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%2F21911%2F1876ae12-555f-408e-81d2-2f43e3a1355d.png</url>
      <title>Forem: MapleLeaf</title>
      <link>https://forem.com/mapleleaf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mapleleaf"/>
    <language>en</language>
    <item>
      <title>TailwindCSS vs. UnoCSS</title>
      <dc:creator>MapleLeaf</dc:creator>
      <pubDate>Mon, 01 May 2023 06:36:04 +0000</pubDate>
      <link>https://forem.com/mapleleaf/tailwindcss-vs-unocss-2a53</link>
      <guid>https://forem.com/mapleleaf/tailwindcss-vs-unocss-2a53</guid>
      <description>&lt;p&gt;I’m a long time &lt;a href="https://tailwindcss.com"&gt;TailwindCSS&lt;/a&gt; user and a huge fan of utility CSS in general. I’ve rarely felt a strong need to switch, but &lt;a href="https://unocss.dev/"&gt;UnoCSS&lt;/a&gt; has been on my mind for a bit. I got around to using it properly, so I thought it’d be fun to write up my thoughts on both in detail.&lt;/p&gt;

&lt;p&gt;This article includes a lot of small nitpicky stuff that may not matter to others, but for me, the more I can reduce microfriction, the better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;Tailwind has class names for pretty much every CSS feature you could think of, including some useful ones you may not know about, like &lt;code&gt;isolation&lt;/code&gt;. Even for what’s missing, with arbitrary values, variants, and properties, most apps can be styled head-to-toe without a custom CSS file or plugins.&lt;/p&gt;

&lt;p&gt;Uno supports all of Tailwind, plus some extras of the box that I really appreciate, like variant groups, fluid columns with CSS grid, and a lot more animations.&lt;/p&gt;

&lt;p&gt;Uno also has an opt-in &lt;a href="https://unocss.dev/presets/attributify"&gt;"attributify" transform&lt;/a&gt;, but I personally prefer my class names to stay in a single attribute separate from props. It's a neat idea though.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Language
&lt;/h2&gt;

&lt;p&gt;Tailwind has a reasonably well-defined language for class names:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every style is a kebab-cased name, e.g. &lt;code&gt;bg-blue-500&lt;/code&gt;, &lt;code&gt;p-4&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Classes can be prefixed with a variant, like &lt;code&gt;md:&lt;/code&gt;, &lt;code&gt;hover:&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Arbitrary stuff is in &lt;code&gt;[brackets]&lt;/code&gt; , with &lt;a href="https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values"&gt;well-documented differences depending on the context&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's no &lt;em&gt;spec&lt;/em&gt; per se, but I've found it's a very "guessable" system. Based on how other class names work, you try stuff like &lt;code&gt;grid-cols-[4rem,1fr,auto]&lt;/code&gt; and it Just Works™️.&lt;/p&gt;

&lt;p&gt;By contrast, Uno's default preset is regex all the way down. There’s no real “language” per-se, and there’s no standardization, e.g. &lt;code&gt;m4&lt;/code&gt; and &lt;code&gt;m-4&lt;/code&gt; both do the same thing.&lt;/p&gt;

&lt;p&gt;This is intentional on Uno's part; &lt;a href="https://unocss.dev/guide/why"&gt;Uno is all about flexibility.&lt;/a&gt; But I still prefer Tailwind's guardrails and opinionated methodology.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This point is somewhat moot since one would really just use Tailwind's language with Uno. That, and Uno probably works better as a framework to implement &lt;em&gt;your own language&lt;/em&gt; on top of it. Regardless, this is my evaluation if I'm looking at it and its default preset as a userland tool for styling apps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;Both docs sites are beautiful, well-written, and highly usable. But I want to give a special shoutout to Uno's interactive docs, and the accent color shifting is brilliant. Might steal that 🤭&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Styles
&lt;/h2&gt;

&lt;p&gt;Here’s an example of a custom plugin in Tailwind:&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;// adds s-* utilities to apply both width and height&lt;/span&gt;
&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matchUtilities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;s&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;({&lt;/span&gt; &lt;span class="na"&gt;width&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="na"&gt;height&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="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;width&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="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s (almost) the same in Uno:&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;// `s-*` classes to set width and height&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="sr"&gt;/^s-&lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&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;size&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="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;rem`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;rem`&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;autocomplete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s-&amp;lt;num&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For both of these, the class &lt;code&gt;s-4&lt;/code&gt; will give the styles &lt;code&gt;width: 1rem; height: 1rem&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Tailwind’s plugin API has gotten a lot nicer over the years. Simple utilities are easy to add, and even more complex ones like in this example aren’t that bad either.&lt;/p&gt;

&lt;p&gt;Uno makes heavy use of regex for dynamic utilities, which feels error-prone. Uno encourages defining utilities that can take whatever value you give it, which reduces the need for the &lt;code&gt;[]&lt;/code&gt; arbitrary value syntax. But I still prefer how Tailwind limits you to a specific set of values.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Aside: Tailwind’s arbitrary value syntax &lt;em&gt;also&lt;/em&gt; lets you use any value. But the docs, plus the syntax required to use it, discourages them from being used. I like the clear, enforced sentinel of “this does not exist in the design system”.&lt;br&gt;
By contrast, Uno more or less &lt;em&gt;encourages&lt;/em&gt; users to use whatever value they want. Although you technically could build a more constrained design system within Uno, that's more leaps than what you get with Tailwind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Editor Support
&lt;/h2&gt;

&lt;p&gt;Tailwind’s editor support works pretty well, but has some gaps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No awareness of custom classes in CSS files

&lt;ul&gt;
&lt;li&gt;It'll autocomplete classes in CSS with &lt;code&gt;@apply&lt;/code&gt;, but &lt;a href="https://github.com/tailwindlabs/tailwindcss-intellisense/issues/227"&gt;it won't autocomplete custom classes from CSS in HTML&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Does not autocomplete class names when using &lt;code&gt;@apply&lt;/code&gt; in plugins&lt;/li&gt;
&lt;li&gt;You need to configure an “experimental” option with custom regex to get completion contexts elsewhere, and you need to dig through issues and discussions to find the recipe you want. Which &lt;em&gt;still&lt;/em&gt; may not work in all cases, because... y'know, Regex 🫠&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These issues make it tedious to reuse styles, via &lt;code&gt;@apply&lt;/code&gt; or with class name strings in JS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tailwind authors recommend against using &lt;code&gt;@apply&lt;/code&gt; altogether, but I still find it useful for small atomic elements, like buttons, inputs, and links.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Uno highlights class names and gives color hints &lt;em&gt;everywhere&lt;/em&gt;, which is nice if you’re sharing class names in standalone strings, but it is funny to see it highlight “transition” in &lt;code&gt;const transition = useTransition()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By extension, Uno's editor support also works in &lt;code&gt;uno.config.ts&lt;/code&gt;, which is very nice for adding custom reused class names.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Caveat: you have to add &lt;code&gt;// @unocss-include&lt;/code&gt; at the top of the config file to get it to complete class names in it. This works fine with Remix and PostCSS, but it may break in other setups. TBH the plugin should support this OOTB&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, Uno’s autocomplete is finicky in some ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Often you don’t get options for autocomplete until you type a full utility and &lt;code&gt;-&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Shortcuts don’t always get autocompleted, and it’s not really clear why&lt;/li&gt;
&lt;li&gt;Autocomplete inside a variant group e.g. &lt;code&gt;hover:(|)&lt;/code&gt; doesn’t work unless you put a space in it, like &lt;code&gt;hover:(| )&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That aside, I've found Uno's overall editor experience more frictionless than with tailwind.&lt;/p&gt;




&lt;p&gt;Tailwind and Uno have their strengths and weaknesses. I highly appreciate Tailwind’s constraints and clearer authoring language, but if you value flexibility and extra features, you’ll probably like Uno. Uno also has an overall nicer editor experience as of writing, but maybe that’ll change! I’ll be watching both of them closely. 👀&lt;/p&gt;

&lt;p&gt;Honorable mentions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MasterCSS: Didn't really draw me in. Doesn't seem to have a big focus on constraints at all, and its language doesn't feel very ergonomic&lt;/li&gt;
&lt;li&gt;Twind: &lt;a href="https://github.com/tw-in-js/vscode-twind-intellisense/issues/23"&gt;The editor plugin still isn't updated to work with the latest version&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;TypeWind (and similar): I greatly appreciate the effort to have good DX without an extra editor plugin, but TS-based class names are &lt;em&gt;very&lt;/em&gt; unergonomic 😅&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tailwindcss</category>
      <category>css</category>
      <category>unocss</category>
      <category>web</category>
    </item>
    <item>
      <title>Trouble with useEffect running every render? `useEffectRef` to the rescue!</title>
      <dc:creator>MapleLeaf</dc:creator>
      <pubDate>Thu, 21 Jan 2021 06:49:05 +0000</pubDate>
      <link>https://forem.com/mapleleaf/trouble-with-useeffect-running-every-render-useeffectref-to-the-rescue-3fhi</link>
      <guid>https://forem.com/mapleleaf/trouble-with-useeffect-running-every-render-useeffectref-to-the-rescue-3fhi</guid>
      <description>&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Here's the standard contrived &lt;code&gt;Counter&lt;/code&gt; component, except I've added an &lt;code&gt;onChange&lt;/code&gt; prop, so that the parent component can listen to when the count is updated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&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="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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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;span class="mi"&gt;0&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="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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;count&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use the &lt;code&gt;react-hooks&lt;/code&gt; eslint rule, which is built into Create React App, you'll see that it tells you to add &lt;code&gt;onChange&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;count&lt;/code&gt; to the dependency array.&lt;/p&gt;

&lt;p&gt;Usually, the eslint rule is right, and abiding by it will help prevent bugs. But in practice, this can cause the effect to run on &lt;em&gt;every&lt;/em&gt; render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// every render, this callback function is a new, fresh value&lt;/span&gt;
&lt;span class="c1"&gt;// if a state update happens here, or higher up,&lt;/span&gt;
&lt;span class="c1"&gt;// the effect in `Counter` will run,&lt;/span&gt;
&lt;span class="c1"&gt;// and this alert gets called&lt;/span&gt;
&lt;span class="c1"&gt;// ...every update&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;newCount&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;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`new count: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;newCount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No good! We only want to listen to changes, not all updates! 🙃&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Before I continue, &lt;strong&gt;consider this a last resort&lt;/strong&gt;. If you use this for lots of values, then your effects will miss some important updates, and you'll end up with a stale UI. Reserve this for things that change every render, which are usually callback props. For objects, &lt;a href="https://github.com/discord/use-memo-value"&gt;this might work a lot better&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anyway, here's my preferred solution, which I feel aligns well with &lt;a href="https://twitter.com/ryanflorence/status/1125041041063665666"&gt;the intended mindset of hooks&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&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="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onChangeRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="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="nx"&gt;onChangeRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;onChange&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="nx"&gt;onChangeRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onChangeRef&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works because refs have free floating, mutable values. They can be changed without causing re-renders, and aren't a part of the reactive flow, like state and props are.&lt;/p&gt;

&lt;p&gt;Effects run from top to bottom in the component. The first effect runs and updates &lt;code&gt;onChangeRef.current&lt;/code&gt; to whatever callback we've been passed down. Then the second effect runs, and calls it.&lt;/p&gt;

&lt;p&gt;You can package the above in a custom hook for reuse. It comes in handy, especially for callback props.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&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="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onChangeRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useEffectRef&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="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="nx"&gt;onChangeRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onChangeRef&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useEffectRef&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="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="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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;ref&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: the ESLint rule will tell you to add &lt;code&gt;onChangeRef&lt;/code&gt; to the effect dependencies. &lt;em&gt;Any&lt;/em&gt; component-scoped value used in an effect should be a dependency. Adding it isn't a problem in practice; it doesn't change, so it won't trigger re-renders.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternatives
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Call the callback prop while updating the value
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Counter&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="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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&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;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&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;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works well in this contrived example, and this may even be better for your case!&lt;/p&gt;

&lt;p&gt;However, let's say we add a minus button to this component. Then we have to remember to call the callback when that's clicked as well, and for any other potential case it updates. That, and notice we have to put the update logic twice (&lt;code&gt;c + 1&lt;/code&gt;), due to the use of the callback prop. This is somewhat error-prone.&lt;/p&gt;

&lt;p&gt;I find an effect is more future proof, and more clearly conveys the intent of "call &lt;code&gt;onChange&lt;/code&gt; whenever count changes".&lt;/p&gt;

&lt;p&gt;However, this path &lt;em&gt;does&lt;/em&gt; let you avoid mucking around with &lt;code&gt;refs&lt;/code&gt;, so it still makes for a good alternative. Just giving one more potential tool in the toolbox 🛠&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;useCallback&lt;/code&gt; on the parent
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, and is probably the "most correct" solution, but having to &lt;code&gt;useCallback&lt;/code&gt; every time you want to pass a callback prop is unergonomic, and easy to forget.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;// eslint-disable-line&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This could cause future bugs if you need to add a new dependency and forget to. The rule is rarely wrong in practice, only ever if you're doing something weird, like a custom dependency array.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>reacthooks</category>
      <category>advanced</category>
    </item>
    <item>
      <title>Indexing objects in TypeScript</title>
      <dc:creator>MapleLeaf</dc:creator>
      <pubDate>Wed, 31 Jan 2018 01:22:36 +0000</pubDate>
      <link>https://forem.com/mapleleaf/indexing-objects-in-typescript-1cgi</link>
      <guid>https://forem.com/mapleleaf/indexing-objects-in-typescript-1cgi</guid>
      <description>&lt;p&gt;This is a topic that comes up every now and again, so I figured it'd be useful to write a post about it.&lt;/p&gt;

&lt;p&gt;Imagine you have code like this:&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;// an object defining how to display specific user statuses in the UI&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;statusDisplays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;online&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;offline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;busy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Busy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dnd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Do Not Disturb&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="c1"&gt;// fetch the status of a user by their ID&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getUserStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myUserID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// get the displayed status text&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;displayedStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;statusDisplays&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userStatus&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, with strict mode enabled, the last line gives an interesting-looking error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Element implicitly has an 'any' type because type '{ online: string; offline: string; busy: string; dnd: string; }' has no index signature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;...which looks like complete nonsense if you don't really know what's going on. So let's try to break it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Index Signatures
&lt;/h2&gt;

&lt;p&gt;In TypeScript, in order to get an index off of an object, that object's type has to include an index signature on it. Index signatures are often used to define objects used as dictionaries, like the one we have here. An index signature type looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Dictionary&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;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our object is inferred as the type &lt;code&gt;{ online: string; offline: string; busy: string; dnd: string; }&lt;/code&gt; and does not have an index signature included.&lt;/p&gt;

&lt;p&gt;The reason for this is behavior to prevent runtime errors that come from indexing an object by unknown keys. Imagine the API we're using added a new status 'idle'. &lt;code&gt;statusDisplays['idle']&lt;/code&gt; would return &lt;code&gt;undefined&lt;/code&gt; and error when we try to use it. Or worse, fail silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  A straight-forward-ish solution
&lt;/h2&gt;

&lt;p&gt;To solve that problem in JS, it's enough to check first if the key is valid, and TypeScript usually accomodates for these kinds of checks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userStatus&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;statusDisplays&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statusDisplays&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userStatus&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;Unfortunately, this still produces the same error message, &lt;a href="https://github.com/Microsoft/TypeScript/pull/12253#issuecomment-263132208"&gt;for reasons discussed here and in other similar issues&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's a way of getting around that using a helper function:&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;// `PropertyKey` is short for "string | number | symbol"&lt;/span&gt;
&lt;span class="c1"&gt;// since an object key can be any of those types, our key can too&lt;/span&gt;
&lt;span class="c1"&gt;// in TS 3.0+, putting just "string" raises an error&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;hasKey&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;O&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;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;O&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PropertyKey&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="nx"&gt;O&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;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hasKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusDisplays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userStatus&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statusDisplays&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userStatus&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// works fine!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses a few of interesting features you might not be aware of. Namely &lt;a href="https://www.typescriptlang.org/docs/handbook/generics.html"&gt;generics&lt;/a&gt;, &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types"&gt;&lt;code&gt;keyof&lt;/code&gt;&lt;/a&gt;, and &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards"&gt;user-defined type guards&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We use a generic to infer the shape of the object being passed in, to use it in the return type. Here, the &lt;code&gt;O&lt;/code&gt; parameter of &lt;code&gt;hasKey&lt;/code&gt; is inferred as &lt;code&gt;{ online: string; offline: string; busy: string; dnd: string; }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;keyof&lt;/code&gt; is a keyword in TypeScript which accepts a given object type and returns a &lt;a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types"&gt;union type&lt;/a&gt; of its keys. These are equivalent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;StatusKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;online&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;offline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;busy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;dnd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;StatusKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;busy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dnd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we use a type guard here to say that, if this function returns true, any further usage of &lt;code&gt;key&lt;/code&gt; will be of the specified type. Otherwise, it's still just a string.&lt;/p&gt;

&lt;p&gt;All of this works because TypeScript allows us to index any object as long as the index's type is a union of all the possible keys, so it knows that the key is valid. Maybe in the future, using &lt;code&gt;key in obj&lt;/code&gt; will work on its own, but until then, the helper function works well enough.&lt;/p&gt;

&lt;p&gt;If you have any questions or comments, specifically if I left anything out or if anything's unclear, feel free to leave them down below. Thanks for reading!&lt;/p&gt;

</description>
      <category>typescript</category>
    </item>
    <item>
      <title>ES Modules: Default imports are not namespace imports!</title>
      <dc:creator>MapleLeaf</dc:creator>
      <pubDate>Sun, 05 Nov 2017 09:24:54 +0000</pubDate>
      <link>https://forem.com/mapleleaf/es6-modules-and-default-imports-p0</link>
      <guid>https://forem.com/mapleleaf/es6-modules-and-default-imports-p0</guid>
      <description>&lt;p&gt;Here we have two import statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I see both of them in a lot of written code, the former more often than the latter. They &lt;em&gt;seem&lt;/em&gt; to accomplish the same result, but depending on a lot of factors, they can end up doing entirely different things. I wrote this to hopefully clear up the difference between the two, especially for those who might not be aware that there even is a difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Namespace imports
&lt;/h2&gt;

&lt;p&gt;Namespace imports import all of the exported variables from a file under one name. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// my-module.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&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;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt;

&lt;span class="c1"&gt;// main.js&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;stuff&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;./my-module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// stuff is: { foo: 123, bar: 456 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty simple, right? Not much more to explain here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default imports
&lt;/h2&gt;

&lt;p&gt;On the other hand, default imports import a specific default export from another module. That is, the variable exported as &lt;code&gt;export default&lt;/code&gt; in the imported module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// my-module.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// main.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;stuff&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;./my-module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// stuff is: { foo: 123, bar: 456 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The purpose of default exports is to give an attractive interface for importing a single unit of functionality from another module: a single class, a single utility function, and so on. The default export is meant to promote the practice of single-responsibility modules.&lt;/p&gt;

&lt;p&gt;A variable exported normally is tagged under its variable name. &lt;code&gt;export const foo = 123&lt;/code&gt; is exported under the name &lt;code&gt;foo&lt;/code&gt;, and can be imported as &lt;code&gt;foo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The default export of a module is tagged literally under the name &lt;code&gt;default&lt;/code&gt;. With that in mind, we could rewrite the previous example like this to achieve the same result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// my-module.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// main.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;stuff&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;./my-module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// stuff is: { foo: 123, bar: 456 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conclusion: defaults aren't a value magically hidden alongside the normal exports of a module. Defaults are just syntactic sugar built over what's already possible with normal exports.&lt;/p&gt;

&lt;p&gt;However...&lt;/p&gt;

&lt;h2&gt;
  
  
  Default imports are &lt;em&gt;not&lt;/em&gt; namespace imports
&lt;/h2&gt;

&lt;p&gt;...and should not be treated as such. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// my-module.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&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;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt;

&lt;span class="c1"&gt;// main.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;stuff&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;./my-module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The import statement is looking for a default export to use as &lt;code&gt;stuff&lt;/code&gt;, but the module does not have anything exported as default. The script will fail, complaining that &lt;code&gt;default&lt;/code&gt; could not be found in &lt;code&gt;my-module.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;...Except, if you've ever worked with babel, webpack, or other bundlers/transpilers, you'll know that it actually does work sometimes. Why?&lt;/p&gt;

&lt;p&gt;Most modules are written in CommonJS, and because of this, transpilers and bundlers use various strategies to resolve the differences so you can seamlessly use different module systems together. The most common strategy is to take the &lt;code&gt;module.exports&lt;/code&gt; object from the CommonJS module and treat that as the default export.&lt;/p&gt;

&lt;p&gt;In short, in most build pipelines today, the previous example would work as you expect if &lt;code&gt;my-module.js&lt;/code&gt; were written as a CommonJS module.&lt;/p&gt;

&lt;p&gt;Addtitionally, transpilers add a special &lt;code&gt;__esModule&lt;/code&gt; property to the &lt;code&gt;module.exports&lt;/code&gt; object when transpiling from ES modules to CommonJS. This tells module loaders that the original module is written as an ES module, and is meant to be used as an ES module. So the &lt;code&gt;module.exports&lt;/code&gt; to &lt;code&gt;default&lt;/code&gt; strategy described only applies when the library is originally authored in CommonJS.&lt;/p&gt;

&lt;h2&gt;
  
  
  So then, how do I import React?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/facebook/react/blob/743201387246d0cde523700c151550786f0afc2e/packages/react/src/React.js#L75"&gt;From the React repo:&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lot of code in the wild uses a default export, so that appears to be what they went with here. I personally would've gone with a namespaced export myself given the structure of things, but it is what it is. Â¯\_(ãƒ„)_/Â¯&lt;/p&gt;

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

&lt;p&gt;Know your modules' exports, know which module system it uses, and know whether there is or isn't a default export. &lt;a href="http://2ality.com/2014/09/es6-modules-final.html"&gt;Here's a good article on ES modules if you want to learn more.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there's anything I missed, got wrong, or made unclear, feel free to leave a comment. This is my first article here, so feedback is greatly appreciated. Thanks.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>es6</category>
    </item>
    <item>
      <title>Hi, I'm Darius</title>
      <dc:creator>MapleLeaf</dc:creator>
      <pubDate>Tue, 13 Jun 2017 20:03:08 +0000</pubDate>
      <link>https://forem.com/mapleleaf/hi-im-darius-aka-just-nobody-aka-left-pad</link>
      <guid>https://forem.com/mapleleaf/hi-im-darius-aka-just-nobody-aka-left-pad</guid>
      <description>&lt;p&gt;...a.k.a "just nobody", a.k.a left-pad&lt;/p&gt;

&lt;p&gt;I'm 21, and have been coding for about eight years.&lt;/p&gt;

&lt;p&gt;I live in Reynoldsburg, OH, and am unemployed (for now).&lt;/p&gt;

&lt;p&gt;I mostly work with and am fluent in JavaScript (preferably TypeScript), Lua, and Dart.&lt;/p&gt;

&lt;p&gt;I am currently learning more about everything in the frontend world, along with other languages and tech that catch my eye every now and again.&lt;/p&gt;

&lt;p&gt;You can find me on Twitter as &lt;a href="https://twitter.com/kingdaro_" rel="noopener noreferrer"&gt;@kingdaro_&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nice to meet all of you wonderful people.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
