<?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: Brian K</title>
    <description>The latest articles on DEV Community by Brian K (@waltzingpenguin).</description>
    <link>https://dev.to/waltzingpenguin</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%2F736585%2F2cbb0df7-5f78-40eb-87d0-5fde33bca8f5.png</url>
      <title>DEV Community: Brian K</title>
      <link>https://dev.to/waltzingpenguin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/waltzingpenguin"/>
    <language>en</language>
    <item>
      <title>Suspense in Svelte: Writing Components That Don't Care</title>
      <dc:creator>Brian K</dc:creator>
      <pubDate>Tue, 26 Oct 2021 00:10:46 +0000</pubDate>
      <link>https://dev.to/waltzingpenguin/suspense-in-svelte-writing-components-that-dont-care-21aj</link>
      <guid>https://dev.to/waltzingpenguin/suspense-in-svelte-writing-components-that-dont-care-21aj</guid>
      <description>&lt;p&gt;Loading data, managing async requests, and communicating status information back to the end user takes an impressive portion of our time writing web applications.  What would it look like if we could write components that did not care about any part of that?&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Component
&lt;/h2&gt;

&lt;p&gt;Let's write a simple component that displays all the possible evolutions of a Pokemon using the data supplied from &lt;a href="https://pokeapi.co/"&gt;pokeapi.com&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// file: Evolution.svelte&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./link.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getEvolution&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getPokemon&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$lib/data.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getPokemon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;evolution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getEvolution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$pokemon&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;evolution_chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$pokemon&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

{#if $evolution?.length}
  {#each $evolution as id}
    &lt;span class="nt"&gt;&amp;lt;Link&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  {/each}
{:else}
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This Pokemon doesn't evolve!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{/if}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've accomplished our goal!  This component is really simple and straightforward but also does not care about loading states, error handling, or data fetching. Unfortunately, &lt;em&gt;something&lt;/em&gt; has to worry about those aspects in a production application.  What can we do to allow us to write components this simple without compromising?&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Fetching
&lt;/h2&gt;

&lt;p&gt;As part of the "do not care" mantra, we want to avoid knowing if any other component needs the same data.  Let's just make the request and let our data layer worry about caching and pooling requests between various components.&lt;/p&gt;

&lt;p&gt;An implementation of our &lt;code&gt;getPokemon&lt;/code&gt; function might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// File: $lib/data.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;swr&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@svelte-drama/swr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;suspend&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@svelte-drama/swr/plugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getPokemon&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://pokeapi.co/api/v2/pokemon-species/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/`&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;swr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@svelte-drama/swr&lt;/code&gt; will cache every request keyed on the url passed to it.  If multiple components request the same key at the same time, only one request will be made and all the components will be updated when it returns.  If this request has been made before, we can even skip making the request at all and just return the cached data.&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;suspend&lt;/code&gt; plugin here notifies our application that we need certain data and this component isn't ready to render until we have finished fetching that data.  Exactly what that means is in the next section.&lt;/p&gt;

&lt;p&gt;Finally, &lt;code&gt;data&lt;/code&gt; returned here is a Svelte store.  It will start off as &lt;code&gt;undefined&lt;/code&gt; while fetching data, which our component unfortunately does need to be aware of, and will update to our data once the request is finished.&lt;/p&gt;

&lt;h2&gt;
  
  
  Suspense
&lt;/h2&gt;

&lt;p&gt;To fit the final piece of the puzzle, we still need to show loading indicators to the user.  Let's take our &lt;code&gt;&amp;lt;Evolution&amp;gt;&lt;/code&gt; component and wrap it in a page that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// index.svelte&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@svelte-drama/suspense&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Evolution&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Evolution.svelte&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Eevee Evolutions&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Suspense&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Evolution&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt; &lt;span class="err"&gt;133&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;slot=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;slot=&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;An error occurred.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Suspense&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; component here is tied into the &lt;code&gt;suspend&lt;/code&gt; call we made while fetching data.  If any child components (or any of their children) aren't ready to display yet, this component will just show "Loading...".  Once the data comes in, the loading indicator is discard and our components are shown.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isn't this just &lt;code&gt;#await&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;{#await}&lt;/code&gt; in templates is a powerful tool and these tools do not replace it.  If all data fetching and loading indicators happen in a single component, then that is a simpler way to achieve these same goals.&lt;/p&gt;

&lt;p&gt;The difference happens when data loading is spread across multiple components.  A change to the APIs &lt;code&gt;&amp;lt;Evolution&amp;gt;&lt;/code&gt; depends on would only impact that single component.  The loading indicators on our main page do not care which data is needed or where it comes from.  If the &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; component referenced in our &lt;code&gt;&amp;lt;Evolution&amp;gt;&lt;/code&gt; component also fetched data of its own (e.g. prefetching an image of the Pokemon) we don't have to change any code here at all.&lt;/p&gt;

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

&lt;p&gt;This isn't meant to be an in depth explanation for using any of the libraries mentioned here.  For that, consult their documentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@svelte-drama/swr"&gt;@svelte-drama/swr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@svelte-drama/suspense"&gt;@svelte-drama/suspense&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead, hopefully it illuminates their motivations for existing and what problems they are trying to solve.  You can find a full fledged example of the techniques discussed here: &lt;a href="https://pokemon-suspense-demo.vercel.app/"&gt;https://pokemon-suspense-demo.vercel.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>suspense</category>
    </item>
  </channel>
</rss>
