<?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: nibtime</title>
    <description>The latest articles on DEV Community by nibtime (@nibtime).</description>
    <link>https://dev.to/nibtime</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%2F498373%2Fc2b74616-806e-44f9-af92-b9c4be13f9ba.png</url>
      <title>DEV Community: nibtime</title>
      <link>https://dev.to/nibtime</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nibtime"/>
    <language>en</language>
    <item>
      <title>please tell me "why"</title>
      <dc:creator>nibtime</dc:creator>
      <pubDate>Sat, 13 Mar 2021 02:06:57 +0000</pubDate>
      <link>https://dev.to/nibtime/please-tell-me-why-16c4</link>
      <guid>https://dev.to/nibtime/please-tell-me-why-16c4</guid>
      <description>&lt;p&gt;I am currently in a phase, where I am sort of reflecting on my past 1,5 years of web development. I am trying to see how things went and what decisions I could make to improve.&lt;/p&gt;

&lt;p&gt;Sometimes, thinking about what libs and frameworks to use is so hard. There is so much abundance, it is overwhelming. And it just keeps growing.&lt;/p&gt;

&lt;p&gt;I just read &lt;a href="https://twitter.com/dan_abramov/status/1368710730812432389"&gt;this tweet&lt;/a&gt; from  Dan Abramov:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Hell is other people's abstractions"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Made me laugh. It is just so true 😂.&lt;/p&gt;

&lt;p&gt;Committing to fundamental abstractions is one of the things I believe one needs to be most careful about: you will literally get used to thinking in them. I still mourn about the many people who were sold into one of the biggest hoaxes of computer science: "inheritance for code reuse" - The 3 Amigos made some decent cash by selling dogs that "woof" and ducks that "quack".&lt;/p&gt;

&lt;p&gt;I decided for myself, that from now on I will only try out and possibly commit to abstractions if I can see a strong "why". I need to see strong reasons, conceptually, that something is a really good idea. Minimalism and low-key are not just nice, but an absolute must-have.&lt;/p&gt;

&lt;p&gt;I was happy to see, that there can be libs that fulfill my ideals when I discovered &lt;a href="https://github.com/pmndrs/jotai"&gt;jotai&lt;/a&gt; and &lt;a href="https://github.com/pmndrs/zustand"&gt;zustand&lt;/a&gt; for React state. On the very first time I looked into them, I was able to infer this "why". I was able to project into the future, if I write code like that, the experience of doing so will be pleasant and things will turn out well.&lt;/p&gt;

&lt;p&gt;When I looked into Redux it was more like: "Yeah, I get it, it's by no means bad engineering, but I can't see a possible reality where I write code like that." 😅&lt;/p&gt;

&lt;p&gt;I wish, that docs would focus on this "why" aspect more often. Usually, they only tell you "how". There's the obligatory introduction (like the counter sample) and then there are recipes of various sorts. &lt;/p&gt;

&lt;p&gt;But the "how" is only interesting after you committed to the abstraction. Outside the "mental box" of the abstraction, it has no relevance. The "why" is important to decide whether to step into this "mental box" or not. &lt;/p&gt;

&lt;p&gt;Docs rarely provide really strong and convincing support for the "why" (if they do, instant trust explosion). So please tell me "why" more often 🙏.&lt;/p&gt;

</description>
      <category>webdev</category>
    </item>
    <item>
      <title>avoid the "death by a 1000 cuts" performance problem with jotai</title>
      <dc:creator>nibtime</dc:creator>
      <pubDate>Wed, 10 Mar 2021 17:27:12 +0000</pubDate>
      <link>https://dev.to/nibtime/avoid-the-death-by-a-1000-cuts-performance-problem-with-jotai-4mco</link>
      <guid>https://dev.to/nibtime/avoid-the-death-by-a-1000-cuts-performance-problem-with-jotai-4mco</guid>
      <description>&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;I first got aware of a really hard to grasp performance problem of React by &lt;a href="https://svelte.dev/blog/virtual-dom-is-pure-overhead"&gt;this blog post&lt;/a&gt; from Rich Harris: "death by a 1000 cuts".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The danger of defaulting to doing unnecessary work, even if that work is trivial, is that your app will eventually succumb to 'death by a thousand cuts' with no clear bottleneck to aim at once it's time to optimize. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's explore what that means. Let's look at a most simple pattern involving derived React state: Adding two numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setN&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;1&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;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setM&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;1&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;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;m&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;When we just look at this piece of code, there seems to be no problem at all. This component will work smoothly and performance is absolutely no issue. &lt;/p&gt;

&lt;p&gt;Let's observe what happens during React rendering and how this contributes to the "death by a 1000 cuts". &lt;/p&gt;

&lt;p&gt;React components rerender on state or props changes. On every rerender, the function body of the React component will be executed. So on every rerender, the addition (&lt;code&gt;n + m&lt;/code&gt;) gets executed, also when state or props changes happen that do not influence the result of the addition.&lt;/p&gt;

&lt;p&gt;At first sight, this doesn't matter at all. Re-evaluating the addition every time, even if unnecessary, doesn't make any problem. To prevent unnecessary re-evaluation we can do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&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;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But wait, we are only supposed to do that with expensive computations, right? And simple addition is pretty much the cheapest thing there is.&lt;/p&gt;

&lt;p&gt;So we do not memoize such statements and accept a little unnecessary extra work. We accept a "tiny little cut". One or a few of them don't do much harm.&lt;/p&gt;

&lt;p&gt;But as your codebase grows and such "cuts" keep adding up to 1000, at some point the UI could get sluggish and slow somehow and you might have absolutely no idea why that is and what you did wrong (because you actually did nothing wrong).&lt;/p&gt;

&lt;p&gt;Then you are experiencing the "death by a 1000 cuts" performance problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cure
&lt;/h3&gt;

&lt;p&gt;Start memoizing derived state all over your codebase with &lt;code&gt;useMemo&lt;/code&gt;. There is no clear indication about where to start and when it is enough. At some point after doing this, the performance will be OK again. After your application grows further, it might pop up again and you have to repeat the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redemption
&lt;/h3&gt;

&lt;p&gt;Design your state patterns bottom-up with &lt;a href="https://github.com/pmndrs/jotai"&gt;jotai&lt;/a&gt; atoms. Then this problem has no opportunity to manifest itself by design!&lt;/p&gt;

&lt;p&gt;Let's take a closer look at the core abstraction of jotai, the atom, and how we build patterns of state with it. Let's look how we would model the above addition with jotai:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nAtom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;atom&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mAtom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;atom&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sumAtom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;atom&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nAtom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mAtom&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;Component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setN&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAtom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nAtom&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;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setM&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAtom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mAtom&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;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useAtom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sumAtom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Component behaves the same as the snippet with &lt;code&gt;useState&lt;/code&gt; from above. With one difference: &lt;code&gt;sum&lt;/code&gt; will only be re-evaluated when either n or m changes. So &lt;code&gt;useMemo&lt;/code&gt; is sort of "built-in".&lt;/p&gt;

&lt;p&gt;Let's explore those atom declarations and their meaning. &lt;code&gt;nAtom&lt;/code&gt; and &lt;code&gt;mAtom&lt;/code&gt; are so-called "primitive atoms". They are a readable and writable container for a single number. With &lt;code&gt;useAtom&lt;/code&gt; we can interact with this container inside React components with the same interface that &lt;code&gt;useState&lt;/code&gt; gives us.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sumAtom&lt;/code&gt; is a so-called "derived atom". It is a readable-only container that holds the sum of the current values of &lt;code&gt;nAtom&lt;/code&gt; and &lt;code&gt;mAtom&lt;/code&gt;. This container "knows", that it only needs to re-evaluate its value when one of its dependencies (&lt;code&gt;nAtom&lt;/code&gt;, &lt;code&gt;mAtom&lt;/code&gt;) change. Those dependencies are tracked with the &lt;code&gt;get&lt;/code&gt; function. With &lt;code&gt;useAtom&lt;/code&gt; we can interact with this container inside React components and get the derived value (the sum) directly.&lt;/p&gt;

&lt;p&gt;By designing state with atoms in this bottom-up fashion, we always end up with a minimal "dependency/data flow graph" for our state, where the derived state gets only re-evaluated if one of its (transitive) dependencies changes.&lt;/p&gt;

&lt;p&gt;If that sounds too fancy: it's basically the same thing that spreadsheets do, just replace "atom" with "cell" 😉&lt;/p&gt;

&lt;p&gt;We always just do the minimum necessary work. No "cuts" are happening.&lt;/p&gt;

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