<?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: Alex Reardon</title>
    <description>The latest articles on DEV Community by Alex Reardon (@alexandereardon).</description>
    <link>https://dev.to/alexandereardon</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%2F161784%2F3457f3e3-7475-4bbf-8338-8c6f2ce09b47.png</url>
      <title>DEV Community: Alex Reardon</title>
      <link>https://dev.to/alexandereardon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexandereardon"/>
    <language>en</language>
    <item>
      <title>Wait for pending: A Suspense algorithm exploration</title>
      <dc:creator>Alex Reardon</dc:creator>
      <pubDate>Tue, 25 Jun 2024 05:05:35 +0000</pubDate>
      <link>https://dev.to/alexandereardon/wait-for-pending-a-not-great-alternative-suspense-algorithm-1gdl</link>
      <guid>https://dev.to/alexandereardon/wait-for-pending-a-not-great-alternative-suspense-algorithm-1gdl</guid>
      <description>&lt;p&gt;There is some &lt;a href="https://github.com/facebook/react/issues/29898"&gt;great discourse&lt;/a&gt; going on about how &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; timing should work in &lt;code&gt;react@19&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this post I explore what a &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; algorithm would look like if all pending promises in a &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; boundary were resolved before trying to re-render.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This started as a scratch pad, then a proposal, then I saw some problems with the approach... but I thought I would record and share it all the same. Maybe it might lead to some other &lt;em&gt;better&lt;/em&gt; ideas!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  TLDR
&lt;/h3&gt;

&lt;p&gt;'Wait for pending' is an interesting variation of the &lt;code&gt;react@18&lt;/code&gt; and &lt;code&gt;react@19&lt;/code&gt; (alpha) &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; algorithms. For flat async trees, 'wait for pending' allows for fast calling of render functions, and minimal re-renders. For trees with nested async components, child async components will have their initial render called slower than the &lt;code&gt;react@18&lt;/code&gt; algorithm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; in &lt;code&gt;react@18&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;render all possible components inside a &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; boundary.&lt;/li&gt;
&lt;li&gt;Re-render when any promise resolves&lt;/li&gt;
&lt;li&gt;Continue until no more components throw a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Results in lots of rerenders, but allows parallelization of 'fetch in render' calls, and all components will have their render called as quickly as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; in &lt;code&gt;react@19&lt;/code&gt; (alpha)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stop rendering tree when a component throws a promise&lt;/li&gt;
&lt;li&gt;wait for promise to resolve&lt;/li&gt;
&lt;li&gt;re-render tree&lt;/li&gt;
&lt;li&gt;Continue until no more components throw a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Results in minimal rerenders - but causes 'fetch in render' calls to be sequential (waterfall)&lt;/p&gt;

&lt;h2&gt;
  
  
  'Wait for pending' algorithm
&lt;/h2&gt;

&lt;p&gt;Here is an &lt;em&gt;idea&lt;/em&gt; for &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; timing ('wait for pending'):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always render siblings, even when they throw (like &lt;code&gt;Suspense&lt;/code&gt; in &lt;code&gt;react@18&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Don't re-render children until &lt;em&gt;all&lt;/em&gt; currently thrown promises are resolved.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Let's see how it goes!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;'Wait for pending' is similar to the current &lt;code&gt;react@18&lt;/code&gt; &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; algorithm, except that rather than rendering all children when &lt;em&gt;any&lt;/em&gt; thrown promise resolves, only render when all currently thrown promises resolve.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allows for 'fetch in render' in siblings to trigger parallel fetches&lt;/li&gt;
&lt;li&gt;Still has a great story for pre-fetching&lt;/li&gt;
&lt;li&gt;Reduces the waste caused by re-rendering possibly expensive components&lt;/li&gt;
&lt;li&gt;Expensive component renders along side siblings that &lt;code&gt;throw&lt;/code&gt; will still be redundant. But, at least these redundant renders are reduced&lt;/li&gt;
&lt;li&gt;👎 Can slow down nested 'fetch in render' calls (see below)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Rough algorithm&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;render children&lt;/li&gt;
&lt;li&gt;if no thrown promises, done - otherwise go to step 3&lt;/li&gt;
&lt;li&gt;wait for &lt;em&gt;all&lt;/em&gt; thrown promises to resolve&lt;/li&gt;
&lt;li&gt;go to step 1.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example 1: Only siblings
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;A&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;B&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;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, both &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; have a &lt;code&gt;fetch&lt;/code&gt; for data in their render&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;react@18&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Render 1&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 2&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise from &lt;code&gt;A&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 3&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise from &lt;code&gt;B&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;react@19&lt;/code&gt; alpha timing
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Render 1&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 2&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise from &lt;code&gt;A&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;A&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;B&lt;/code&gt;, but &lt;code&gt;B&lt;/code&gt; throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 3&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise from &lt;code&gt;B&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;A&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;B&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;😢 causes waterfalls if you fetch (throw) in renders&lt;br&gt;
😊 avoids excessive re-rendering potentially expensive components&lt;/p&gt;
&lt;h4&gt;
  
  
  Wait for pending
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Render 1&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;wait for &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; to resolve&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 2&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ In this case, the proposed algorithm yields great results!&lt;/p&gt;
&lt;h3&gt;
  
  
  Example 2: With children
&lt;/h3&gt;

&lt;p&gt;Here is where 'wait for pending' strains.&lt;/p&gt;

&lt;p&gt;Now &lt;code&gt;A&lt;/code&gt; renders children &lt;code&gt;ChildX&lt;/code&gt; and &lt;code&gt;ChildY&lt;/code&gt; which also do a 'fetch in render'&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;A&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;ChildX&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;ChildY&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;A&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;B&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;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;react@18&lt;/code&gt; algorithm
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Render 1&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 2&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise thrown by &lt;code&gt;A&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildX&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildY&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 3&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise thrown by &lt;code&gt;ChildX&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildX&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildY&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 4&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise thrown from &lt;code&gt;ChildY&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildX&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildY&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 5&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise thrown from &lt;code&gt;B&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildX&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildY&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;code&gt;ChildX&lt;/code&gt; and &lt;code&gt;ChildY&lt;/code&gt; get rendered as early as possible&lt;br&gt;
😢 Lots of redundant re-rendering&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;react@19&lt;/code&gt; alpha algorithm
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Render 1&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 2&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise from &lt;code&gt;A&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;A&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;ChildX&lt;/code&gt;, but &lt;code&gt;B&lt;/code&gt; throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 3&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise from &lt;code&gt;ChildX&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;A&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;ChildX&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;ChildY&lt;/code&gt;, but &lt;code&gt;ChildY&lt;/code&gt; throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 4&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise from &lt;code&gt;ChildY&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;A&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;ChildX&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;ChildY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;B&lt;/code&gt;, but &lt;code&gt;B&lt;/code&gt; throws a promise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 5&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise from &lt;code&gt;B&lt;/code&gt; resolves&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;A&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;ChildX&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;ChildY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;render &lt;code&gt;B&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Proposed algorithm
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Render 1&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;wait for &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; to resolve&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 2&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise thrown by &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; resolve&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildX&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildY&lt;/code&gt; renders, but throws a promise&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;wait for &lt;code&gt;ChildX&lt;/code&gt; and &lt;code&gt;ChildY&lt;/code&gt; to resolve&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Render 3&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise thrown by &lt;code&gt;ChildX&lt;/code&gt; and &lt;code&gt;ChildY&lt;/code&gt; resolve&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;A&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildX&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ChildY&lt;/code&gt; renders&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;B&lt;/code&gt; renders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ A lot less redundant rendering than the &lt;code&gt;react@18&lt;/code&gt; algorithm&lt;br&gt;
👎 &lt;code&gt;ChildX&lt;/code&gt; and &lt;code&gt;ChildY&lt;/code&gt; need to wait for &lt;code&gt;B&lt;/code&gt; to resolve before kicking off their 'fetch in render' calls. They had to wait for the slowest sibling of their parent to resolve before they could kick off their promises.&lt;br&gt;
🤔 More parellisation than the &lt;code&gt;react@19&lt;/code&gt; algorithm, but slower to kick off initial renders for all components than &lt;code&gt;react@18&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;'Wait for pending' is an interesting approach.&lt;/p&gt;

&lt;p&gt;For flat async trees, 'wait for pending' allows for fast calling of render functions, and minimal re-renders. However, when there trees with nested async components, async child components have to wait for their parents siblings to finish rendering before their initial render function is called. If the nested component was doing an expensive operation (such as a network call), then triggering the initial renders as quickly as possible is ideal (the &lt;code&gt;react@18&lt;/code&gt; algorithm). The 'wait for pending' is similar to the &lt;code&gt;react@19&lt;/code&gt; approach - except that each level can be parellised.&lt;/p&gt;

&lt;p&gt;It was interesting to think about what a different &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; algorithm could look like! Thanks for making it this far 😅.&lt;/p&gt;

&lt;p&gt;Cheers&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Commute Rule</title>
      <dc:creator>Alex Reardon</dc:creator>
      <pubDate>Sun, 21 Aug 2022 23:15:06 +0000</pubDate>
      <link>https://dev.to/alexandereardon/the-commute-rule-5g9o</link>
      <guid>https://dev.to/alexandereardon/the-commute-rule-5g9o</guid>
      <description>&lt;p&gt;&lt;strong&gt;The Commute Rule&lt;/strong&gt;: If you are too sick to commute to the office, don’t work from home&lt;/p&gt;

&lt;p&gt;This year I have fallen into a bad habit: being moderately sick, but pushing through the sickness and working from home. Since the beginning of COVID I have been working from home. Something I have become aware of is that the barrier to get to work when working from home is extremely low. All I need to do is slink over to my desk, sit upright and clink away on my keyboard. I usually can do that even when I am moderately unwell.&lt;/p&gt;

&lt;p&gt;In the past I have written about why I think it is important that we rest when we are sick: &lt;a href="https://www.atlassian.com/blog/productivity/take-real-sick-days-work-life-balance"&gt;Take a real sick day&lt;/a&gt; and I still stand by that.&lt;/p&gt;

&lt;p&gt;Taking time to recover well seems to lead to shorter illnesses&lt;/p&gt;

&lt;p&gt;Working while moderately sick is pretty miserable for everybody and fosters a culture where people feel pressured to work while unwell&lt;/p&gt;

&lt;p&gt;Taking a &lt;em&gt;real&lt;/em&gt; sick day challenges us to find our self worth outside of our outputs&lt;/p&gt;

&lt;p&gt;Sometimes we can be "sick" and it is mild, and has no real impact on our days (eg a small cough). What I needed was some good general rule that I could use for myself that would help me decide whether I was too sick to work from home. A rule I came up with was &lt;strong&gt;the commute rule&lt;/strong&gt;: If I don’t think I am well enough to have a shower, get changed, walk to the train station, catch a train for 45m to the city and walk to the office; then I should not work from home. If I was working in the office, I would not be going to work if I was unable to do the commute. I can apply the same test for working from home.&lt;/p&gt;

&lt;p&gt;This rule isn't perfect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;People have different commutes&lt;/li&gt;
&lt;li&gt;You might be not wanting to commute due to infectiousness, and not ability&lt;/li&gt;
&lt;li&gt;Probably a few other reasons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even though this rule isn’t perfect, I have personally found it useful I thought I would share it.&lt;/p&gt;

&lt;p&gt;I hope you are doing well,&lt;/p&gt;

&lt;p&gt;Cheers&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title>How to grow as a software engineer</title>
      <dc:creator>Alex Reardon</dc:creator>
      <pubDate>Mon, 28 Mar 2022 22:04:00 +0000</pubDate>
      <link>https://dev.to/alexandereardon/how-to-grow-as-a-software-engineer-4o17</link>
      <guid>https://dev.to/alexandereardon/how-to-grow-as-a-software-engineer-4o17</guid>
      <description>&lt;p&gt;In this blog I share some advice on how to grow as a software engineer that I have collected through my own experiences, reading and observations.&lt;/p&gt;

&lt;p&gt;In the space of about 17 years I have personally grown from not knowing programming at all to being a Principal Engineer at Atlassian. I have built some cool things I am proud of and I have worked with some amazing people. I have been involved in mentoring, interviewing and promotions, and I have some practice in thinking about how to guide, level and grow engineers.&lt;/p&gt;

&lt;p&gt;This blog is targeted at people who are entering into the software industry. The content of this blog was originally given as a presentation to University students. I cover a fair amount of ground in a relatively short period of time. I hope that my words can carry you into deeper thought and exploration.&lt;/p&gt;

&lt;p&gt;Giving general advice is a difficult exercise as few things are universally true. I acknowledge my advice is likely shaped by my privilege as a white native english speaking male (hard to escape my own bias).&lt;/p&gt;

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

&lt;p&gt;In order to grow as a software engineer, there are three parallel and overlapping areas that you will want to improve in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;👩‍💻 Technical proficiency&lt;/li&gt;
&lt;li&gt;👀 Contextual awareness&lt;/li&gt;
&lt;li&gt;✍️ Communication skills&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In addition to talking about these areas, I will also give some general pointers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You are worth more than your outputs&lt;/li&gt;
&lt;li&gt;Be kind to yourself&lt;/li&gt;
&lt;li&gt;Adopt a learners mindset&lt;/li&gt;
&lt;li&gt;Dangerous accelerant: side projects&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's do this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Area 1: 👩‍💻 Technical proficiency
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;How well do you know the programming language(s) and technologies that you are working with?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Master the fundamentals
&lt;/h3&gt;

&lt;p&gt;The foundation of your value as a software engineer is technical proficiency. You want to pursue an ever increasing understanding and familiarity with the programming language(s) and technologies that you work with day to day. A strong technical proficiency will allow you to craft robust, clean, valuable and creative solutions.&lt;/p&gt;

&lt;p&gt;You will want to get a good grip on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Foundational language building blocks, such as: variables, loops, functions, conditions, type systems, type coercion, classes, objects, collections, input and output and so on.&lt;/li&gt;
&lt;li&gt;Language grammar and semantics (don't shy away from the hard parts - even if you don't use them right away, you might encounter them or find use for them at some point)&lt;/li&gt;
&lt;li&gt;Scoping rules (what things can be accessed when, and by what)&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;Code reuse and sharing patterns&lt;/li&gt;
&lt;li&gt;Asynchronous behaviour&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are &lt;em&gt;so many ways&lt;/em&gt; you can grow in technical proficiency, and I don't think there is any one &lt;em&gt;right&lt;/em&gt; way. Find some option(s) that you find interesting and motivating.&lt;/p&gt;

&lt;p&gt;Here are some ideas for how you can grow your technical proficiency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read technical books&lt;/li&gt;
&lt;li&gt;Read industry newsletters&lt;/li&gt;
&lt;li&gt;Watch courses&lt;/li&gt;
&lt;li&gt;Attend meetups&lt;/li&gt;
&lt;li&gt;Attend conferences&lt;/li&gt;
&lt;li&gt;Read blogs&lt;/li&gt;
&lt;li&gt;Listen to podcasts&lt;/li&gt;
&lt;li&gt;Create your own side project (more on side projects later!)&lt;/li&gt;
&lt;li&gt;Get involved in open source (make your own project, contribute to another, read the source another)&lt;/li&gt;
&lt;li&gt;Experiment, fiddle! Find a way for you to run cheap little experiments to validate behaviour and try things out&lt;/li&gt;
&lt;li&gt;Seek understanding of why something does not work (or does work)&lt;/li&gt;
&lt;li&gt;Find (safe) people and learning communities you can ask questions to (eg twitter, reddit)&lt;/li&gt;
&lt;li&gt;Share your learning with others (blogs, meetups, book clubs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My memory is pretty terrible, and knowledge that I don't use regularly tends to fade. I think that is a pretty common experience. So what I do is learn where I can find good information on particular topics, even if I cannot remember all the specifics about the topic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Get the fundamentals down and the level of everything you do will rise" - Michael Jordan&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Ask questions about your code
&lt;/h3&gt;

&lt;p&gt;Over time, you should get comfortable asking deeper questions of your code. Knowing how to gather good answers to the following questions will increase your impact and effectiveness:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How confident am I that my code is behaving how I expect? (&lt;strong&gt;types, testing, language familiarity&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;How do I go about troubleshooting problems in my code? (&lt;strong&gt;debugging&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tip from &lt;a href="https://twitter.com/AndaristRake"&gt;@AndaristRake&lt;/a&gt;: logging is great for debugging (eg with &lt;code&gt;console.log()&lt;/code&gt;), but learning to leverage a proper debugger can power you up quite a bit&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do I know if my code is working in production? (&lt;strong&gt;monitoring&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;How many people are using my code and how are they using it? (&lt;strong&gt;analytics&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;How can I use a server to do actions for me: tests, linting, releasing and so on? (&lt;strong&gt;continious integration&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;What are the performance characteristics of my code? (&lt;strong&gt;profiling, benchmarking&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;How do people learn how to use my code successfully? (&lt;strong&gt;documentation&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;How can people of differing abilities interact with the software I make? (&lt;strong&gt;accessibility&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;How can I (safely?) evolve my system over time? (&lt;strong&gt;migrations, evolutions&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Not all questions will apply to every language / stack, but you will get the broad idea&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding and balancing tradeoffs
&lt;/h3&gt;

&lt;p&gt;There is rarely a perfect solution to any problem in computer science. As software engineers, we are always balancing tradeoffs. Over time you will want to become familiar with identifying and balancing the benefits and drawbacks of solutions.&lt;/p&gt;

&lt;p&gt;You will grow in your understanding relevant tradeoffs by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compare answers to [↑ See: &lt;em&gt;Ask questions about your code&lt;/em&gt;]&lt;/li&gt;
&lt;li&gt;[↓ See: &lt;em&gt;Bare the consequences of your choices&lt;/em&gt;]&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Weighing tradeoffs often involves considering many non-technical considerations as well [See: ↓ &lt;em&gt;Area 2: Contextual awareness&lt;/em&gt;].&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Explore popular industry solutions
&lt;/h3&gt;

&lt;p&gt;For your programming language, are there popular libraries or frameworks for solving common problems? Give them a go! See how they feel to you. Try to gain an understanding of the solutions benefits and drawbacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bare the consequences of your choices
&lt;/h3&gt;

&lt;p&gt;When we create code, it will generally go through a number of high level phases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creation&lt;/li&gt;
&lt;li&gt;Iteration and long term ownership&lt;/li&gt;
&lt;li&gt;Deletion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideally, you want to try to get experience with the entire lifecycle. You won't know how particular choices pan out straight away. Often it takes extended periods of time, multiple consumers, changing requirements and so on, to expose the true benefits and drawbacks of various technical choices. You can then feed these learnings into future decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version control
&lt;/h3&gt;

&lt;p&gt;In order to successfully collaborate with other engineers, you will need to have a working knowledge of a version control tool: &lt;code&gt;git&lt;/code&gt;. At this point I wouldn't recommend you learn alternative version control systems unless you need to. A &lt;em&gt;working knowledge&lt;/em&gt; of &lt;code&gt;git&lt;/code&gt; is a good mental model as well as familiarity with the basic commands. &lt;code&gt;git&lt;/code&gt; is also a gateway getting a server to automatically perform actions on your code (test, lint, deploy and so on).&lt;/p&gt;

&lt;p&gt;Thankfully, there are lots of fantastic &lt;code&gt;git&lt;/code&gt; learning materials which a light Google search will reveal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Area 2: 👀 Contextual awareness
&lt;/h2&gt;

&lt;p&gt;Your (beautiful) code does not exist in a vacuum. You will be more effective the more you can appreciate the multiple wider contexts that your efforts fall into.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical context
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Gain a good &lt;em&gt;general&lt;/em&gt; 'full stack' understanding&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For many engineers, you will be working on applications that span multiple layers of technologies. If you work in one of those environments, it is fantastic to gain a working understanding of all of the layers in that stack. Understanding more about the requirements, features, constraints, strengths and weaknesses of various layers in the stack you work in will help you to create solutions (or pieces of solutions) that plays into the strengths of various layers.&lt;/p&gt;

&lt;p&gt;I am not advocating that you need to become a 'full stack engineer', rather, that you have 'full stack appreciation'.&lt;/p&gt;

&lt;h3&gt;
  
  
  Team context
&lt;/h3&gt;

&lt;p&gt;Growing as an engineer also means helping the other people around you be successful too. Being a lone star on a project is not a healthy long term model for any project. Helping other people be successful has a multiplication effect for your project. What are the tools, processes and systems that can help your teammates be successful?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We rise by lifting others" ― Robert Ingersoll&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Business context
&lt;/h3&gt;

&lt;p&gt;Having an understanding of the business (or project) you work for, and it's goals will help you align your efforts and advocacy. I have seen many initiatives and creative solutions be adopted because the driver of the solution understood the business goals and needs. You can burn time trying to redirect a business (or project) in a direction that &lt;em&gt;you think&lt;/em&gt; is great, but doesn't line up well with it's goals. There is a time and a place for encouraging redirections - but it is helpful to know when you are pushing with or against the currently planned destination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Industry context
&lt;/h3&gt;

&lt;p&gt;While software engineering and problem domain foundations don't really change all that often, there is a constant evolution of ideas and offerings.&lt;/p&gt;

&lt;p&gt;There can be benefits in observing larger industry trends:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exposure to new techniques, projects and tools&lt;/li&gt;
&lt;li&gt;Sanity check your ideas against existing solutions&lt;/li&gt;
&lt;li&gt;Identity market opportunities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How can you keen up to date with industry trends? Similar methods to how you can grow in your technical proficiency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read industry newsletters&lt;/li&gt;
&lt;li&gt;Watch courses&lt;/li&gt;
&lt;li&gt;Attend meetups&lt;/li&gt;
&lt;li&gt;Attend conferences&lt;/li&gt;
&lt;li&gt;Read blogs&lt;/li&gt;
&lt;li&gt;Listen to podcasts&lt;/li&gt;
&lt;li&gt;Join learning communities&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Area 3: ✍️ Communication skills
&lt;/h2&gt;

&lt;p&gt;The reality of creating software is that you will be communicating (a lot) with other people. Regardless of whether you are a solo open source developer or an employee at a mega software corp - communicating well with others is critical to your effectiveness.&lt;/p&gt;

&lt;p&gt;I can almost feel some people cringe as they read this. You might be thinking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I just want to write code! I didn't go into software to become a people person!"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I can empathise with this. I am not advocating you need to become a highly articulate and eloquent socialite - rather, that you grow into being able to share clear and helpful information with other people. That doesn't sound too bad - does it?&lt;/p&gt;

&lt;p&gt;Good communication leads to increased alignment and clarity, so that you, and the people you interact with, can focus on constructive things. Poor communication leads to a lot of friction, frustration and wasted effort for you, your teammates, your organisation and your users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code authoring
&lt;/h3&gt;

&lt;p&gt;The code we write is just as much for communicating with your future self, and for other people, as it is for the machine to execute. Being able to have clear ways of communicating your intention and rationales in your code is essential for code that needs live more than a few weeks. Writing code that is easy to follow is a strong signal of engineering seniority as it demonstrates the understanding that code will need to be well understood by someone that lacks context at a later date.&lt;/p&gt;

&lt;p&gt;Some general tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimise for readability (this covers a lot of things)&lt;/li&gt;
&lt;li&gt;Avoid 'magic one liners'.&lt;/li&gt;
&lt;li&gt;If you &lt;em&gt;really&lt;/em&gt; need hard to read code, hide it behind a nice API&lt;/li&gt;
&lt;li&gt;Use comments when you think something requires additional information that is not apparent looking at the code itself&lt;/li&gt;
&lt;li&gt;Types (and their names) can be a great way to communicate extra information&lt;/li&gt;
&lt;li&gt;Prefer explicit behaviour rather than implicit&lt;/li&gt;
&lt;li&gt;Only enforce style preferences that are backed by automatic tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Code reviews
&lt;/h3&gt;

&lt;p&gt;Reviewing code (often through a 'pull request') is a common industry practice to help ensure software quality. There is so much to say about pull requests - you will find heaps of tips after a light Google search.&lt;/p&gt;

&lt;p&gt;Pull requests are communication intensive. When you are creating a pull request, or reviewing it, you want to aim to be as clear as you can and who needs to do what. Pursing clarity in pull requests will lead to higher quality changes and for potential changes to be accepted / rejected faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Persuasion
&lt;/h3&gt;

&lt;p&gt;Other people will need to make decisions based on information that you provide them. Here are some questions people might approach you, or your outputs with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which solution should we adopt?&lt;/li&gt;
&lt;li&gt;Why should we invest in your idea?&lt;/li&gt;
&lt;li&gt;Why should I buy your product?&lt;/li&gt;
&lt;li&gt;Why should I adopt your open source project?&lt;/li&gt;
&lt;li&gt;Why should I hire you?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using established persuasive communication techniques can help make connections between a need and a solution clear and straightfoward.&lt;/p&gt;

&lt;p&gt;Persuasive communication is a skill that can be learned and improved. I personally was exposed to formal persuasive communication through a law degree (that I otherwise do not use much now). But a small Google search will reveal a number of blogs and courses on how you can learn and improve at persuasive communication.&lt;/p&gt;

&lt;p&gt;For me, persuasive communication is not about tricking people, but about making your proposed value propositions clear and easy to follow. Doing this well will help others buy in or opt out more quickly, and for the right reasons.&lt;/p&gt;

&lt;h2&gt;
  
  
  General pointers
&lt;/h2&gt;

&lt;p&gt;I have shared three general areas for you to focus on improving in order to grow as an software engineer. Here is a collection of other thoughts that you might also find helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pointer 1: You are worth more than your outputs
&lt;/h3&gt;

&lt;p&gt;My limited and subjective experience is that if you choose to define your self worth based on your outputs you will never be truly satisfied. Your self worth will rise and fall in proximity to your most recent success. I strongly believe the all human beings have dignity and worth is not tied to their outputs. Try to find a way to derive your sence of self worth from something other than your outputs. I am deeply and painfully aware this is no easy task, but I have found increasing joy in trying to decouple my self worth from my outputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pointer 2: Be kind to yourself
&lt;/h3&gt;

&lt;p&gt;You could spend all your time and effort becoming a great software engineer, and you would probably become one. Being good at your craft is awesome, but I think there is also so much more of the human experience for you to enjoy. If you work in software engineering, you will likely have many decades of working ahead of you. It's okay to take your time and enjoy the journey.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pointer 3: Adopt a learners mindset
&lt;/h3&gt;

&lt;p&gt;A great way to encourage your long term growth is to adopt a position where knowledge is not secret, but learnable (and forgettable!)&lt;/p&gt;

&lt;p&gt;Some tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask lots of questions&lt;/li&gt;
&lt;li&gt;Be okay with saying "I don't know" (espeically as you get more senior - it is license for more junior folks)&lt;/li&gt;
&lt;li&gt;Find ways that let you answer questions on your own quickly&lt;/li&gt;
&lt;li&gt;Be open to changing your mind on things. &lt;em&gt;Try&lt;/em&gt; not to emotionally invest in technical positions because it can make it harder to change your mind when you should&lt;/li&gt;
&lt;li&gt;Challenge existing ideas&lt;/li&gt;
&lt;li&gt;It is okay to forget things (even basic things). It is very human. Be open about calling out that you don't remember something.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pointer 4: Dangerous accelerant: side projects
&lt;/h3&gt;

&lt;p&gt;I have a love hate relationship with side projects.&lt;/p&gt;

&lt;p&gt;Side projects could be things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating an open source library&lt;/li&gt;
&lt;li&gt;Contributing to an open source library&lt;/li&gt;
&lt;li&gt;Making your own product&lt;/li&gt;
&lt;li&gt;Making your own game&lt;/li&gt;
&lt;li&gt;Creating digital art&lt;/li&gt;
&lt;li&gt;Soo many more things (I don't want to limit you!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Side projects often put you in the drivers seat of a project and let you leverage your personal time to have more agency to execute on creative / risky things often with little consequences. Side projects are a powerful vehicle of personal growth on many vectors. However, they are a &lt;em&gt;dangerous accelerant&lt;/em&gt;. It is easy to soak up significant amounts of your time with side projects. Speaking from painful personal experience - side projects can cost you more than were expecting to pay. Should you do a side project if you have the opportunity and inclination? For sure! But be careful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://egghead.io/podcasts/alex-reardon-on-balancing-work-life-and-large-side-projects"&gt;More reflections of mine on side projects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Thanks
&lt;/h2&gt;

&lt;p&gt;I hope you find the advice I have shared helpful. Thanks to the people who helped review and give feedback on this blog.&lt;/p&gt;

&lt;p&gt;You can follow me on twitter at &lt;a href="https://twitter.com/alexandereardon"&gt;@alexandereardon&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers&lt;/p&gt;

</description>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Gardening</title>
      <dc:creator>Alex Reardon</dc:creator>
      <pubDate>Tue, 21 Jan 2020 21:55:17 +0000</pubDate>
      <link>https://dev.to/alexandereardon/gardening-1a1d</link>
      <guid>https://dev.to/alexandereardon/gardening-1a1d</guid>
      <description>&lt;p&gt;I was standing in my backyard and I could see lots that needed to be done: hedge trimming, grass mowing, dead branches to be removed, and so much more. I started on consolidating some unused flower pots into a single spot. While doing that I thought it would be a good idea to remove an overgrown fern. I pulled the fern down and then got distracted by the idea of some other task.&lt;/p&gt;

&lt;p&gt;My Dad, who is a gardening enthusiast, arrived about an hour later to drop off some tools. He took a look around at my yard and gave me some advice. He encouraged me to finish one job completely and to tidy up any mess before moving onto the next job. Without realising I had started three or four different jobs - all currently at different levels of completion. My Dad's logic was that you might be interrupted at any point and you don't want to be in a position where you are left with large cleanup jobs, or where you have to leave the yard in a bad state with unfinished and dangerous things around.&lt;/p&gt;

&lt;p&gt;I spent the next few hours going through each of the jobs I had started earlier and finished them one by one, cleaning up as I went. I didn't get through as much of the gardening as I would have liked that day (things had a bad habit of taking longer than I expected) but everything I started I finished. I could come back another day to do the remaining jobs. The yard was left tidy and the kids could enjoy it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Focus on one task at a time. Get it done. Tidy up. Then move on&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title>Overhauling our collision engine</title>
      <dc:creator>Alex Reardon</dc:creator>
      <pubDate>Thu, 05 Dec 2019 03:24:06 +0000</pubDate>
      <link>https://dev.to/alexandereardon/overhauling-our-collision-engine-962</link>
      <guid>https://dev.to/alexandereardon/overhauling-our-collision-engine-962</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;How we created a more delightful drag and drop experience&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Drag and drop is a very human interaction: pick something up and move it somewhere else. &lt;a href="https://github.com/atlassian/react-beautiful-dnd"&gt;&lt;code&gt;react-beautiful-dnd&lt;/code&gt;&lt;/a&gt; (&lt;code&gt;rbd&lt;/code&gt;) is an open source library we created at Atlassian that attempts to reflect the &lt;strong&gt;physicality&lt;/strong&gt; of this human interaction in order to provide a more relatable experience.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;rbd&lt;/code&gt; contains logic for calculating what should move out of way of the dragging item, and what droppable area the dragging item is currently over (&lt;strong&gt;the collision engine&lt;/strong&gt;). Over time, some limitations of the collision engine have emerged. This blog will share our journey rebuilding the collision engine in order to make drag and drop more delightful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 1: Knowing when to move
&lt;/h2&gt;

&lt;p&gt;The original collision engine used the centre position of the &lt;em&gt;dragging item&lt;/em&gt; to determine what other items should move out of the way. An item would move out of the way when the centre position of the dragging item goes over the start or end edge of another item.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"a dragging items impact is based on its centre of gravity — regardless of where a user grabs an item from" - &lt;a href="https://medium.com/@alexandereardon/rethinking-drag-and-drop-d9f5770b4e6b"&gt;Rethinking drag and drop&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;✅ When items are &lt;strong&gt;roughly the same size&lt;/strong&gt; then the interaction is all good&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k2ti8k4R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/ggm3k1so672o9yta3q24.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k2ti8k4R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/ggm3k1so672o9yta3q24.gif" alt="reordering similar sized items" width="400" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;✅ Using the centre position of the dragging item holds up when dragging &lt;strong&gt;large items next to small items&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8We43P8q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/0zbeicfvqxszcd33be6t.png" class="article-body-image-wrapper"&gt;&lt;img alt="collision diagram" src="https://res.cloudinary.com/practicaldev/image/fetch/s--8We43P8q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/0zbeicfvqxszcd33be6t.png" width="800" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;❌ Using the centre position of the dragging item &lt;strong&gt;does not work well when dragging small items next to large items&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L6jB3IHe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/hiyciyj62nzxfwcso1xd.png" class="article-body-image-wrapper"&gt;&lt;img alt="collision diagram" src="https://res.cloudinary.com/practicaldev/image/fetch/s--L6jB3IHe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/hiyciyj62nzxfwcso1xd.png" width="800" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, when moving a small item past a big item, the big item would satisfy the condition to move up (the dragging centre is after the top edge), and once moved up, it would satisfy the condition to move down (the dragging centre is before the bottom edge). This would cause big item not being dragged to flicker up and down.&lt;/p&gt;

&lt;p&gt;We overcame this weakness in the &lt;strong&gt;old&lt;/strong&gt; collision engine by checking different edges depending on what direction the user was heading in. For example, when moving down in a list we only check to see if the centre of the dragging item has gone past the top edge of another item.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KHz91od1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/36ynsoi1r3z77vjd0kor.png" class="article-body-image-wrapper"&gt;&lt;img alt="collision diagram" src="https://res.cloudinary.com/practicaldev/image/fetch/s--KHz91od1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/36ynsoi1r3z77vjd0kor.png" width="800" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This solution (&lt;em&gt;hack&lt;/em&gt;) was not without drawbacks. When dragging large items next to small items, things quickly turn into a &lt;strong&gt;dumpster fire&lt;/strong&gt; if the user changed directions quickly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AtpMqc5E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/pmbhwwvlxzij75vnoku4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AtpMqc5E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/pmbhwwvlxzij75vnoku4.gif" alt="large-items-sucked" width="300" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XSjlUxUS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/p2zja3j8a82h1b2r1ycv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XSjlUxUS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/p2zja3j8a82h1b2r1ycv.png" alt="oh no" width="554" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When dragging large items next to small ones, small direction changes could result in quite a different displacement of items.&lt;/p&gt;

&lt;p&gt;So yeah, things were not great.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution: Flipping the logic
&lt;/h2&gt;

&lt;p&gt;The shortcomings of the collision engine have lingered on in the &lt;code&gt;rbd&lt;/code&gt; repo for quite some time. There was an open question as to how to maintain &lt;strong&gt;physicality,&lt;/strong&gt; while also overcoming problems with using the centre position of the dragging item.&lt;/p&gt;

&lt;p&gt;About a month ago we got a fantastic suggestion from &lt;a href="https://github.com/caspersmith"&gt;@caspersmith&lt;/a&gt;: &lt;em&gt;flip the logic&lt;/em&gt;. Rather than using the centre position of the dragging item for determining displacement, look at the centre position of the &lt;em&gt;other items&lt;/em&gt;. When an &lt;strong&gt;edge of the dragging item&lt;/strong&gt; goes over the &lt;strong&gt;centre position of another item&lt;/strong&gt;, then move that item out of the way. It turned out that this idea holds up extremely well mathematically and still feels great.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---2i-v81P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/cgw3cyfhdf64qd0ofvng.png" class="article-body-image-wrapper"&gt;&lt;img alt="collision diagram" src="https://res.cloudinary.com/practicaldev/image/fetch/s---2i-v81P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/cgw3cyfhdf64qd0ofvng.png" width="800" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By using the edges of the dragging item we can never end up in a situation where we hit the same item before and after it is displaced, regardless of the items size. The new approach also means we no longer need to lean on the user direction (hack).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_LO_Lnm4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/htc22buntwna25sqtyc0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_LO_Lnm4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/htc22buntwna25sqtyc0.gif" alt="big-item-fixed" width="300" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wGOhCJdo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/ftktagfz6ofprbrxr03r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wGOhCJdo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/ftktagfz6ofprbrxr03r.gif" alt="success" width="320" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem 2: What is being dragged over?
&lt;/h2&gt;

&lt;p&gt;When dragging something around we need to communicate to the user what droppable area the dragging item is currently over. Previously we did this by &lt;strong&gt;exclusively using the centre position of the dragging item&lt;/strong&gt;. This is done in an attempt to make the dragging item feel more physical:  by using the centre position we are using the dragging item's centre of mass to control its location.&lt;/p&gt;

&lt;p&gt;✅ Things feel fantastic when lists are &lt;strong&gt;roughly the same size&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pw87G76B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/zydxc4vh8kf5elsyjkjl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pw87G76B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/zydxc4vh8kf5elsyjkjl.gif" alt="between-two-lists" width="500" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;❌ Significant problems arise when a user is trying to &lt;strong&gt;drag a large item into a small list&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9d6YP7P5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/01na7au8ztzpph9xwu5a.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9d6YP7P5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/01na7au8ztzpph9xwu5a.gif" alt="big lists broken" width="700" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can be jarring (and sometimes impossible) for users to drag a big item into a small list. They need to line up the centre position of the big item over this list - which can require overshooting the list with your cursor to get the centre position in the right spot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XSjlUxUS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/p2zja3j8a82h1b2r1ycv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XSjlUxUS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/p2zja3j8a82h1b2r1ycv.png" alt="oh no" width="554" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution: Understanding intention
&lt;/h2&gt;

&lt;p&gt;We spent &lt;em&gt;many&lt;/em&gt; hours whiteboarding various potential strategies to improve the experience for dragging large items into small areas. I think we lost a few years of our lives during this process.&lt;/p&gt;

&lt;h3&gt;
  
  
  The new approach
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Find &lt;strong&gt;drop candidates 🙋‍♀️&lt;/strong&gt;(droppable areas that &lt;em&gt;could&lt;/em&gt; be the active area)&lt;/li&gt;
&lt;li&gt;Choose the &lt;strong&gt;drop candidate furthest away&lt;/strong&gt; from where the drag start started&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Finding drop candidates 🙋‍♀️
&lt;/h3&gt;

&lt;p&gt;Previously there was only one way to determine what the droppable area would be: the dragging item centre position. We have now added more ways for droppable areas to be the active droppable area.&lt;/p&gt;

&lt;p&gt;A droppable area can be a &lt;strong&gt;drop candidate&lt;/strong&gt; when&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Centre hit (existing)&lt;/strong&gt;: the centre position of the dragging item is over the droppable area&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cross axis hit (new)&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(this logic only comes into play when dragging large items into smaller sized areas)&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is &lt;strong&gt;some&lt;/strong&gt; overlap of the dragging item and the droppable area; and&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only one&lt;/strong&gt; edge of the dragging item is over the list on the cross axis of the droppable area; and&lt;/li&gt;
&lt;li&gt;The edge must have &lt;strong&gt;gone past the cross axis centre&lt;/strong&gt; of the droppable area (&lt;code&gt;end edge &amp;gt; cross axis centre line&lt;/code&gt;, &lt;code&gt;start edge &amp;lt; cross axis centre line&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Totally covered on cross axis (new)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The dragging item is &lt;strong&gt;totally&lt;/strong&gt; over a droppable area on the cross axis&lt;/li&gt;
&lt;li&gt;There is &lt;strong&gt;some&lt;/strong&gt; overlap on the main axis&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3LR10YQZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/sghxsm48kc33i6ctkp74.png" class="article-body-image-wrapper"&gt;&lt;img alt="detected candidates" src="https://res.cloudinary.com/practicaldev/image/fetch/s--3LR10YQZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/sghxsm48kc33i6ctkp74.png" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose candidate that is furthest away
&lt;/h3&gt;

&lt;p&gt;When there are &lt;strong&gt;multiple drop candidates&lt;/strong&gt; (multiple drop areas that we think the user is over) &lt;strong&gt;we choose the one that is furthest away from where the drag started&lt;/strong&gt;. There will only be multiple drop candidates when dragging large items over small droppable areas, so this logic doesn't come into play for the standard use case of dragging items over areas that are of a similar size on the cross axis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rZePCTYa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/2bxriw7t9nmu3pcakpy9.png" class="article-body-image-wrapper"&gt;&lt;img alt="furthest away diagram" src="https://res.cloudinary.com/practicaldev/image/fetch/s--rZePCTYa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/2bxriw7t9nmu3pcakpy9.png" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Determining what drop candidate is furthest away is not as straightforward as measuring the distance between the centre points of the droppable areas (which is what we started with). Doing that gives preference to giant droppable areas as their centres are often far away. Rather, we measure the distance between where the dragging item started, the point at which the dragging item hits the cross axis of the droppable area.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NW2gczCy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/ncophvj0sistm3ilrn1a.png" class="article-body-image-wrapper"&gt;&lt;img alt="calculating distance between lists" src="https://res.cloudinary.com/practicaldev/image/fetch/s--NW2gczCy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/ncophvj0sistm3ilrn1a.png" width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What does the new approach achieve?
&lt;/h3&gt;

&lt;p&gt;When droppable areas are &lt;strong&gt;roughly the same size&lt;/strong&gt; on the cross axis, things will operate in the same way they did before: the centre position will be used to control what droppable area an item is over (which feels great)&lt;/p&gt;

&lt;p&gt;Strictly using the dragging items centre position was our ideal situation for all interactions. But, as we have seen, using the centre doesn't work well for &lt;strong&gt;moving big items into small lists&lt;/strong&gt;. We looked for a solution would best respect the users &lt;strong&gt;intention&lt;/strong&gt;. We landed on the view that when a draggable item hits a new droppable area it is likely that the user is trying to move into that area - so that is what we will try to give preference to. That is why we give preference to areas that are further away from where the user started. Doing this also requires the least amount of movement to move something into a new area.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We decided this new strategy for large items was a necessary divergence from the physicality of &lt;code&gt;rbd&lt;/code&gt; in order to provide an experience that feels intuitive and delightful for users, which in the end, is what we are pursuing physicality to achieve.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2OtGWTQ---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/4gykiy1tevqzy2ku5tlx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2OtGWTQ---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/4gykiy1tevqzy2ku5tlx.gif" alt="large-items-nice" width="697" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks
&lt;/h2&gt;

&lt;p&gt;We hope you have enjoyed this blog, and that you and the people who use your software enjoy the overhauled &lt;code&gt;rbd&lt;/code&gt; collision engine. The new collision is available in the &lt;code&gt;12.2.0&lt;/code&gt; release of &lt;a href="https://github.com/atlassian/react-beautiful-dnd"&gt;&lt;code&gt;rbd&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to all the Atlassian's who helped work on this and to &lt;a href="https://twitter.com/danieldelcore"&gt;Daniel Del Core&lt;/a&gt;, &lt;a href="https://twitter.com/itsmadou"&gt;Michael Dougall&lt;/a&gt; and &lt;a href="https://twitter.com/vennsoh"&gt;Ee Venn Soh&lt;/a&gt; who helped put this blog together.&lt;/p&gt;

&lt;p&gt;Cheers&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>ux</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What does react-beautiful-dnd cost to maintain?</title>
      <dc:creator>Alex Reardon</dc:creator>
      <pubDate>Tue, 21 May 2019 01:08:13 +0000</pubDate>
      <link>https://dev.to/alexandereardon/what-does-react-beautiful-dnd-cost-to-maintain-52e8</link>
      <guid>https://dev.to/alexandereardon/what-does-react-beautiful-dnd-cost-to-maintain-52e8</guid>
      <description>&lt;p&gt;The aim of this blog is to make visible the ongoing effort required to maintain the open source drag and drop project &lt;a href="https://github.com/atlassian/react-beautiful-dnd"&gt;&lt;code&gt;react-beautiful-dnd&lt;/code&gt;&lt;/a&gt; (&lt;code&gt;rbd&lt;/code&gt;). The maintenance of the &lt;code&gt;rbd&lt;/code&gt; project will look different to other open source projects, but I thought it would be insightful nonetheless. By exposing maintenance information I hope to dispell the myth that open source projects lead to less total effort then private source. There are huge advantages in open source, but the cost of ownership is not one of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;rbd&lt;/code&gt; is popular and much loved ❤️
&lt;/h2&gt;

&lt;p&gt;I have been lucky enough to work close to full time on the &lt;code&gt;rbd&lt;/code&gt; project for almost two years at &lt;a href="https://www.atlassian.com/"&gt;Atlassian&lt;/a&gt; and I am it's primary maintainer. &lt;code&gt;rbd&lt;/code&gt; is used widely internally (Jira Software, Jira Portfolio, Jira Service desk, Trello and Confluence to name a few) and externally (Facebook, box, Zendesk and much more). It is now in the &lt;a href="https://bestof.js.org/tags/react"&gt;top 20 starred&lt;/a&gt; &lt;code&gt;React&lt;/code&gt; projects and it &lt;a href="https://www.npmtrends.com/react-beautiful-dnd-vs-react-dnd-vs-react-drag-and-drop-vs-react-sortable-hoc-vs-@shopify/draggable"&gt;one of the most downloaded&lt;/a&gt; drag and drop packages on the web. The package has been an ongoing source of praise for Atlassian.&lt;/p&gt;

&lt;h2&gt;
  
  
  The best defence is a good offence 🏈
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Optimising for self-service
&lt;/h3&gt;

&lt;p&gt;I have adopted strategies that aim to maximise peoples ability to get started with &lt;code&gt;rbd&lt;/code&gt;, use &lt;code&gt;rbd&lt;/code&gt;, and troubleshoot issues without needing to reach out directly (&lt;strong&gt;self-service&lt;/strong&gt;). They include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created a free &lt;code&gt;egghead.io&lt;/code&gt; &lt;a href="https://egghead.io/courses/beautiful-and-accessible-drag-and-drop-with-react-beautiful-dnd"&gt;quick start course&lt;/a&gt; to talk people through getting started with the library step by step.&lt;/li&gt;
&lt;li&gt;Created and maintain extensive documentation&lt;/li&gt;
&lt;li&gt;Adding development only &lt;code&gt;console&lt;/code&gt; warnings for detectable setup issues. That way people do not need to consult the docs for most setup issues&lt;/li&gt;
&lt;li&gt;Creating a common setup issue guide&lt;/li&gt;
&lt;li&gt;Creating issue templates to help people to debug their own issues before reaching out&lt;/li&gt;
&lt;li&gt;Using repeated issues as a signal for unclear documentation or a good development only warning&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  No open bugs 🐛❌
&lt;/h3&gt;

&lt;p&gt;I have taken a fairly bold stance with &lt;code&gt;rbd&lt;/code&gt;: &lt;strong&gt;I will not ship any new features while there are open bugs&lt;/strong&gt;. This might seem unobtainable, but &lt;code&gt;rbd&lt;/code&gt; has now been using this strategy successfully for almost two years. By keeping the quality bar high I have reduced the need for people to reach out. This lowers the amount of time I need to spend on maintenance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Rant 🌶
&lt;/h4&gt;

&lt;p&gt;It is hard to know if a bug is trivial or if it exposes a foundational issue. In order to confidently move forward with a software project we need to know that what we are building on is solid - otherwise, we can drown in fixes and rework. When people use a project they want it to work. It is okay for a project to have limitations - but to not deliver on what it claims to do is &lt;strong&gt;trust-destroying&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workload 👷‍♂️
&lt;/h2&gt;

&lt;p&gt;I have mentioned that I do a lot to promote self-service of &lt;code&gt;rbd&lt;/code&gt;. However, people still do reach out for a variety of reasons. These collectively add up to &lt;strong&gt;a rough average of one day a week of work&lt;/strong&gt;. The amount of effort &lt;strong&gt;fluctuates&lt;/strong&gt; week to week.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bug reports 🐛
&lt;/h3&gt;

&lt;p&gt;I get about &lt;strong&gt;one bug report every 1-2 days&lt;/strong&gt;. There are a few types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ghost issue&lt;/strong&gt;: an issue is created without much detail or an example. I ask for more information and a demo (I provide a boilerplate demo). I then hear nothing back, ever. I need to then come in some time later and close the issue. I let them know they can reopen the issue if they provide more information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simple setup issue&lt;/strong&gt;: some issues raised can be resolved by simply telling people to look at their console (as it can already be telling them what their issue is and how to fix it), or pointing them to our documentation. A large amount of these come from people who are getting started with &lt;code&gt;React&lt;/code&gt; and &lt;code&gt;rbd&lt;/code&gt; is in one of their first projects. So often people are fighting with &lt;code&gt;React&lt;/code&gt; issues rather than &lt;code&gt;rbd&lt;/code&gt; issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex setup issues&lt;/strong&gt;: sometimes bug like behaviours will be present in complex examples that people post. After a lot of investigation, I find that the answer was a &lt;strong&gt;simple setup issue&lt;/strong&gt; that was hiding under layers of complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limitation hit&lt;/strong&gt;: people hit against a documented limitation of the library. The limitation needs to be explained, and any relevant issues or documentation linked to. Sometimes this might lead to a new feature request issue being added, or additional detail added to an existing feature request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actual bug&lt;/strong&gt;: actual bugs get raised and need to be fixed. I need to diagnose the bug, do a root cause analysis, design a solution, write a fix, write tests, merge the fix and do a release. Some bugs are simple problems with obvious fixes. Some expose much deeper issues. Sometimes I will release a short term fix if there is one available if I know that the correct fix will take a longer amount of effort. I will reproduce the provided example with a bug in a local environment to develop &lt;code&gt;rbd&lt;/code&gt; against. Sometimes a bug can be fixed in an hour, sometimes two days. Sometimes it requires it change in architecture which might occur slowly over months.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setup and limitation issues can also lead to documentation and development only warning improvements. Ideally, we make everything as clear as possible to people. I use repeating issues as a signal&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature requests 🚀
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;rbd&lt;/code&gt; gets feature requests for a large number of interactions. These need to be run through our guiding principles and evaluated. Sometimes I think it fits into the direction of the library and keep the request open. This might be the start of a discussion as we figure out the implications and implementation details of the feature. Other times the request does not line up the direction of the project and I provide an explanation and close the issue. I might also add this information to the project philosophy page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discussions 🗣
&lt;/h3&gt;

&lt;p&gt;We have a number of open discussion threads running at a time. This is for features and ideas that still require more thinking. These can be lengthy back and forth conversations and API, use cases, implementation, testing and implications. I often do a lot of background (shower) thinking about these.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pull requests
&lt;/h3&gt;

&lt;p&gt;We get about &lt;strong&gt;one pull request to the &lt;code&gt;rbd&lt;/code&gt; project per week&lt;/strong&gt;. There are a number of categories&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Documentation fix: almost always can be easily merged&lt;/li&gt;
&lt;li&gt;Proposed code changes: either a bug fix or new feature. &lt;strong&gt;Rarely created and even more rarely merged&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Proposed code changes
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;React&lt;/code&gt; team put it nicely when they said that rarely do they accept changes from external contributors. The &lt;code&gt;React&lt;/code&gt; project has a rich history and established future direction. It is hard for an outsider to come in and make a meaningful contribution to the core library. I have found this also to be true for &lt;code&gt;rbd&lt;/code&gt;. Changes on the fringes of the project are welcome and encouraged: documentation, build improvements, types, examples and (minor) bug fixes. &lt;strong&gt;But external contributors generally lack the context to make bigger changes&lt;/strong&gt;. We do get some from time to time, but they often an attempt to meet their own goals without thinking more broadly about the library. I have found that these proposed changes are often in conflict with the accessibility or philosophy of the project. I generally encourage people to reach out before undertaking large engineering efforts to discuss what approach the change should take:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hack: work with existing or new APIs to achieve their use case&lt;/li&gt;
&lt;li&gt;Fork: maintain a forked version which bakes in their behaviour&lt;/li&gt;
&lt;li&gt;Contribute: &lt;code&gt;rbd&lt;/code&gt; could use the feature. In my experience, we have not had a single feature contributed entirely by an external. Sometimes I can shepherd through a bug fix. An additional challenge is their skill levels. On a few occasions, I have needed to rework big parts of external pull requests&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Moderating 👩‍⚖️
&lt;/h3&gt;

&lt;p&gt;There are 50+ active issues in &lt;code&gt;rbd&lt;/code&gt;. They are comprised of feature requests, discussions, improvements and ideas. I monitor them to provide input and to ensure that the code of conduct is being observed. I try to respond to people within 48 hours. I also need to close old or redundant issues. I also get pinged questions through Twitter, Stack Overflow and other channels occasionally. I will either answer directly if it is simple or push them towards the project page to create an issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharing 🎁
&lt;/h3&gt;

&lt;p&gt;There is some really interesting engineering in &lt;code&gt;rbd&lt;/code&gt;. I write blogs and give talks to share my learnings and to market the &lt;code&gt;rbd&lt;/code&gt; project. By doing this the impact of &lt;code&gt;rbd&lt;/code&gt; is bigger than just the project itself. I will often spend 0.5-2 days writing a blog, 0.5-1 day preparing for speaking at a meetup and 3-5 days preparing for a conference talk. There is also a lot of thinking, exploring and discussions before creating sharable content.&lt;/p&gt;

&lt;h4&gt;
  
  
  Project related blogs
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@alexandereardon/rethinking-drag-and-drop-d9f5770b4e6b"&gt;Rethinking drag and drop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@alexandereardon/friction-gravity-and-collisions-3adac3a94e19"&gt;Natural keyboard movement between lists&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@alexandereardon/beautiful-drag-and-drop-a-year-in-review-1febc3fac7ce"&gt;Beautiful drag and drop: a year in review&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@alexandereardon/beautiful-interactions-8f67502ccf73"&gt;Beautiful interactions: Crafting elegant and robust drag and drop animations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Performance related blogs
&lt;/h4&gt;

&lt;p&gt;Sharing some of my performance engineering learnings from &lt;code&gt;rbd&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@alexandereardon/grabbing-the-flame-290c794fe852"&gt;Grabbing the flame 🔥&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@alexandereardon/dragging-react-performance-forward-688b30d40a33"&gt;Dragging React performance forward&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@alexandereardon/performance-optimisations-for-react-applications-b453c597b191"&gt;Performance optimisations for React applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@alexandereardon/performance-optimisations-for-react-applications-round-2-2042e5c9af97"&gt;Performance optimisations for React applications: Round 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Talks
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=MVi17tk3VsI"&gt;Deep sea fishing with React Hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.meetup.com/Sydney-Web-Accessibility-Inclusive-Design/events/258868400"&gt;Creating beautiful and accessible drag and drop for Atlassian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=g_3e_bNU2e0"&gt;Rate limiting from scratch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.webdirections.org/wds18/speakers/alex-reardon.php"&gt;What’s in the box?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=sI83N5OeNGI"&gt;React Portal: the good, the bad and the ugly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=3REMkuIg23k"&gt;Dragging React performance forward&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=jm81fmVr3co"&gt;Performance optimisations for React: round 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=TsAIo05s0DQ"&gt;Performance optimisations for React applications&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=hbCwF3QVr7o"&gt;Performance hacking React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;30+ at an internal Atlassian front end meetup&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Internal Atlassian maintenance
&lt;/h3&gt;

&lt;p&gt;All of the issue tracking and discussions for &lt;code&gt;rbd&lt;/code&gt; is done on Github - so for the most, there are no double updates required for issues internally. However, there are internal &lt;code&gt;rbd&lt;/code&gt; tasks as well. They include: creating and updating high level project tracking issues, meeting with internal stakeholders about future needs, internal blogs and planning discussions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;Maintaining &lt;code&gt;rbd&lt;/code&gt; &lt;strong&gt;takes a lot&lt;/strong&gt; of ongoing work. It is enjoyable to maintain a project with this scale - but it is heavy. Maintenance has been made easier by proactively pursuing self-service and continuing to engage with the project. In the times that I have needed to focus on other things, I know that the maintenance for the project has slipped as it is a fairly daunting domain to keep on top of.&lt;/p&gt;

&lt;p&gt;I hope you have found this window into the maintenance cost of &lt;code&gt;rbd&lt;/code&gt; insightful. Also a huge thanks to Atlassian for continuing to allow me to invest into &lt;code&gt;rbd&lt;/code&gt; ✌️&lt;/p&gt;

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