<?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: Michael Thiessen</title>
    <description>The latest articles on DEV Community by Michael Thiessen (@michaelthiessen).</description>
    <link>https://dev.to/michaelthiessen</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%2F107692%2Fe508c8a0-372a-4940-90a1-41b38d473d4d.jpeg</url>
      <title>DEV Community: Michael Thiessen</title>
      <link>https://dev.to/michaelthiessen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michaelthiessen"/>
    <language>en</language>
    <item>
      <title>13 Vue Composables Tips You Need to Know</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Fri, 10 Jan 2025 15:42:00 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/13-vue-composables-tips-you-need-to-know-1ifg</link>
      <guid>https://dev.to/michaelthiessen/13-vue-composables-tips-you-need-to-know-1ifg</guid>
      <description>&lt;p&gt;Vue composables are incredibly powerful, but they can quickly become messy and hard to maintain if you're not careful.&lt;/p&gt;

&lt;p&gt;That's why I've identified 13 tips that will help you write better, more maintainable composables.&lt;/p&gt;

&lt;p&gt;Whether you're building a simple state management solution or complex shared logic, these tips will help you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid common pitfalls that lead to spaghetti code&lt;/li&gt;
&lt;li&gt;Write composables that are easier to test and maintain&lt;/li&gt;
&lt;li&gt;Create more flexible and reusable shared logic&lt;/li&gt;
&lt;li&gt;Gradually migrate from Options API to Composition API if you need to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tips you'll learn are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Avoid Prop Drilling Through Multiple Components&lt;/li&gt;
&lt;li&gt;Share Data Between Unrelated Components&lt;/li&gt;
&lt;li&gt;Control State Updates with Clear Methods&lt;/li&gt;
&lt;li&gt;Break Up Large Components into Smaller Functions&lt;/li&gt;
&lt;li&gt;Separate Business Logic from Vue Reactivity&lt;/li&gt;
&lt;li&gt;Handle Both Sync and Async Data in One Function&lt;/li&gt;
&lt;li&gt;Make Function Parameters More Descriptive&lt;/li&gt;
&lt;li&gt;Prevent Undefined Options with Default Values&lt;/li&gt;
&lt;li&gt;Return Simple or Complex Values Based on Needs&lt;/li&gt;
&lt;li&gt;Separate Different Logic Paths into Their Own Functions&lt;/li&gt;
&lt;li&gt;Handle Reactive and Raw Values Consistently&lt;/li&gt;
&lt;li&gt;Simplify Ref Unwrapping&lt;/li&gt;
&lt;li&gt;Migrate from Options API to Composition API Gradually&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's dive into each pattern and see how they can improve your Vue applications.&lt;/p&gt;

&lt;p&gt;And don't forget, comment below with your favourite tip!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Avoid Prop Drilling Through Multiple Components
&lt;/h2&gt;

&lt;p&gt;The Data Store Pattern can help avoid passing props and events through multiple component layers.&lt;/p&gt;

&lt;p&gt;One situation is where you have a parent and child communicating through endless prop drilling and event bubbling:&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="c"&gt;&amp;lt;!-- Parent.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- But many more layers of components --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Child&lt;/span&gt; &lt;span class="na"&gt;:user=&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"onUserChange"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onUserChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;updatedUser&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a lot of complexity since those props and events have to move back and forth through the component hierarchy.&lt;/p&gt;

&lt;p&gt;A more straightforward solution is to create a shared data store that any component can import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toRefs&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useUserStore&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="nf"&gt;toRefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Share Data Between Unrelated Components
&lt;/h2&gt;

&lt;p&gt;The Data Store Pattern also helps when sibling or “cousin” components need to share the same data without any direct connection.&lt;/p&gt;

&lt;p&gt;Suppose two siblings both require the same user object, but there's no elegant path for props or events.&lt;/p&gt;

&lt;p&gt;This often results in awkward data juggling through a parent or duplicated state.&lt;/p&gt;

&lt;p&gt;A better approach is to rely on a single composable store that both siblings can consume:&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;// SiblingA.vue&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;useUserStore&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;./useUserStore&lt;/span&gt;&lt;span class="dl"&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;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useUserStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// SiblingB.vue&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;useUserStore&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;./useUserStore&lt;/span&gt;&lt;span class="dl"&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;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useUserStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Control State Updates with Clear Methods
&lt;/h2&gt;

&lt;p&gt;The Data Store Pattern encourages providing clear methods for updating shared state.&lt;/p&gt;

&lt;p&gt;Some developers expose the entire reactive object to the world, 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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That lets anybody change the user’s darkMode property directly from any file, which can lead to scattered, uncontrolled mutations.&lt;/p&gt;

&lt;p&gt;A better idea is to return the state as read only along with functions that define how updates happen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;readonly&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleDarkMode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;darkMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;darkMode&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useUserStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;readonly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;toggleDarkMode&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;h2&gt;
  
  
  4. Break Up Large Components into Smaller Functions
&lt;/h2&gt;

&lt;p&gt;The Inline Composables Pattern helps break up large components by gathering related state and logic into smaller functions.&lt;/p&gt;

&lt;p&gt;A giant component might put all its refs and methods in one place:&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 &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;// 500 more lines of intertwined code with watchers, methods, etc.&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That setup quickly becomes unmanageable.&lt;/p&gt;

&lt;p&gt;Instead, an inline composable can group logic and provide it locally. We can then extract it into a separate file later on:&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 &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useCounter&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;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCounter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Separate Business Logic from Vue Reactivity
&lt;/h2&gt;

&lt;p&gt;The Thin Composables Pattern tells us to separate raw business logic from Vue reactivity so tests and maintenance become simpler.&lt;/p&gt;

&lt;p&gt;You might embed all logic in the composable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useCounter&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;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;increment&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;That forces you to test logic inside a Vue environment.&lt;/p&gt;

&lt;p&gt;Instead, keep the complicated rules in pure functions and let the composable only handle reactive wrappers:&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;// counterLogic.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;incrementCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// useCounter.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;ref&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;vue&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;incrementCount&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;./counterLogic&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="nf"&gt;useCounter&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;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;incrementCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;increment&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;h2&gt;
  
  
  6. Handle Both Sync and Async Data in One Function
&lt;/h2&gt;

&lt;p&gt;The Async + Sync Composables Pattern merges both synchronous and asynchronous behaviors into one composable instead of creating separate functions.&lt;/p&gt;

&lt;p&gt;This is just like how Nuxt's &lt;code&gt;useAsyncData&lt;/code&gt; works.&lt;/p&gt;

&lt;p&gt;Here we have a single composable that can return a promise while also giving immediate reactive properties for synchronous usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&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;vue&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="nf"&gt;useAsyncOrSync&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Make Function Parameters More Descriptive
&lt;/h2&gt;

&lt;p&gt;The Options Object Pattern can clear up long lists of parameters by expecting a single config object.&lt;/p&gt;

&lt;p&gt;Calls like this are cumbersome and prone to mistakes, and adding new options requires updating the function signature:&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="nf"&gt;useRefHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;someRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s not obvious what each argument stands for.&lt;/p&gt;

&lt;p&gt;A composable that accepts an options object keeps everything descriptive:&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="nf"&gt;useRefHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;someRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;deep&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;immediate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Prevent Undefined Options with Default Values
&lt;/h2&gt;

&lt;p&gt;The Options Object Pattern also recommends default values for each property.&lt;/p&gt;

&lt;p&gt;A function that assumes certain fields exist can be problematic if they aren’t passed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useRefHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;someRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// potential undefined references here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s better to destructure options with safe defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useRefHistory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;someRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;deep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// can safely use deep, capacity, etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Return Simple or Complex Values Based on Needs
&lt;/h2&gt;

&lt;p&gt;The Dynamic Return Pattern makes sure a composable can return either a single value for simple use cases or an expanded object with more advanced controls.&lt;/p&gt;

&lt;p&gt;Some approaches always return an object with everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defaultValue&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;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;remove&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;Anyone who only needs the main reactive value is forced to deal with extra stuff.&lt;/p&gt;

&lt;p&gt;A composable that conditionally returns a single ref or an object solves that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;controls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&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;controls&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;remove&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Separate Different Logic Paths into Their Own Functions
&lt;/h2&gt;

&lt;p&gt;The Hidden Composables Pattern helps avoid mixing mutually exclusive logic in the same composable.&lt;/p&gt;

&lt;p&gt;Some code lumps together multiple modes or code paths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useUserFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// admin logic&lt;/span&gt;
  &lt;span class="c1"&gt;// guest logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Splitting each path into its own composable is much clearer and doesn't affect functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useAdminFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// admin-only logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useGuestFlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// guest-only logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  11. Handle Reactive and Raw Values Consistently
&lt;/h2&gt;

&lt;p&gt;The Flexible Arguments Pattern ensures inputs and outputs in composables are uniformly handled as reactive data or raw values, avoiding confusion.&lt;/p&gt;

&lt;p&gt;Some code checks if an input is a ref or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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;Instead, you can convert right away.&lt;/p&gt;

&lt;p&gt;By using ref, if the input is a ref, that ref will be returned. Otherwise, it will be converted to a ref:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toValue&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;vue&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="nf"&gt;useSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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;asRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;// always a ref&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  12. Simplify Ref Unwrapping
&lt;/h2&gt;

&lt;p&gt;The Flexible Arguments Pattern also uses toValue when unwrapping is needed.&lt;/p&gt;

&lt;p&gt;Without it, code might keep doing isRef checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// if (isRef(msg)) ...&lt;/span&gt;
  &lt;span class="c1"&gt;// else ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s much simpler to call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;toValue&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;vue&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="nf"&gt;useLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&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;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&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;h2&gt;
  
  
  13. Migrate from Options API to Composition API Gradually
&lt;/h2&gt;

&lt;p&gt;The Options to Composition Pattern lets you migrate big Options API components into the Composition API step by step in an incremental way that's easy to follow.&lt;/p&gt;

&lt;p&gt;A classic Options component might do 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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;double&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data, computed properties, and methods are scattered.&lt;/p&gt;

&lt;p&gt;Converting it to script setup pulls them together and makes it easier to follow, and allows you to use these patterns:&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 &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;double&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&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;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping it up
&lt;/h2&gt;

&lt;p&gt;These 13 tips will help you write better Vue composables that are easier to maintain, test, and reuse across your applications.&lt;/p&gt;

&lt;p&gt;But we're just scratching the surface here.&lt;/p&gt;

&lt;p&gt;Over the years, I've collected many more patterns and tips, and I've put them all into an in-depth course on composable patterns.&lt;/p&gt;

&lt;p&gt;It covers 16 patterns in total, and each pattern has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;In-depth explanations&lt;/strong&gt; — when to use it, edge cases, and variations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-world examples&lt;/strong&gt; — so you can see how to use them beyond these simple examples&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step-by-step refactoring examples&lt;/strong&gt; — so you can see how to apply them to your own code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://michaelnthiessen.com/composable-design-patterns" rel="noopener noreferrer"&gt;Go here to learn more&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Oh, and this course is on sale until January 15th, so you can get it for a great discount right now!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/composable-design-patterns"&gt;Check out Composable Design Patterns&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>nuxt</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Ref vs. Reactive — Which is Best?</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Wed, 22 Feb 2023 15:41:15 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/ref-vs-reactive-which-is-best-1ik4</link>
      <guid>https://dev.to/michaelthiessen/ref-vs-reactive-which-is-best-1ik4</guid>
      <description>&lt;p&gt;&lt;em&gt;A huge thanks to everyone who looked at early drafts of this: especially Austin Gil for challenging my arguments, Eduardo San Martin Morote, Daniel Roe, Markus Oberlehner, and Matt Maribojoc&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This has been a question on the mind of every Vue dev since the Composition API was first released:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s the difference between &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt;, and which one is better?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My extremely short answer is this: default to using &lt;code&gt;ref&lt;/code&gt; wherever you can.&lt;/p&gt;

&lt;p&gt;Now, that’s not a very satisfying answer, so let’s take some more time to go through all of the reasons why I think &lt;code&gt;ref&lt;/code&gt; is better than &lt;code&gt;reactive&lt;/code&gt; — and why you shouldn’t believe me.&lt;/p&gt;

&lt;p&gt;Here’s what our journey will look like, in roughly three acts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Act 1: The differences between &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt;&lt;/strong&gt; — First, we’ll go through all of the ways that &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt; are different. I’ll try to avoid giving any judgment at this point so you can see all the ways they’re different.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://michaelnthiessen.com/ref-vs-reactive#act-2-the-ref-vs-reactive-debate" rel="noopener noreferrer"&gt;Act 2:  The &lt;code&gt;ref&lt;/code&gt; vs &lt;code&gt;reactive&lt;/code&gt; debate&lt;/a&gt;&lt;/strong&gt; — Next, I’ll lay out the main arguments for &lt;code&gt;ref&lt;/code&gt; and for &lt;code&gt;reactive&lt;/code&gt;, giving the pros and cons of each. &lt;em&gt;At this point you will be able to make your own well-informed decision.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://michaelnthiessen.com/ref-vs-reactive#act-3-why-i-prefer-ref" rel="noopener noreferrer"&gt;Act 3: Why I prefer &lt;code&gt;ref&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; — I end the article stating my own opinion and sharing my own strategy. I also share what others in the Vue community think about this whole debate, since one person’s opinion only counts for so much (ie. very little).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More than just a discussion of “ref vs. reactive”, I hope that as we explore this question you’ll come away with additional insights that will improve your understanding of the Composition API!&lt;/p&gt;

&lt;p&gt;Also, this is a long article, so if you don’t have time to read it all now, definitely set this aside and come back to it — you’ll thank me later!&lt;/p&gt;

&lt;h2&gt;
  
  
  tl;dr — My highly opinionated and simple strategy
&lt;/h2&gt;

&lt;p&gt;But first, a quick summary of my strategy for choosing.&lt;/p&gt;

&lt;p&gt;With roughly increasing levels of complexity:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start with using &lt;code&gt;ref&lt;/code&gt; everywhere&lt;/li&gt;
&lt;li&gt;Group related things with &lt;code&gt;reactive&lt;/code&gt; if you need to&lt;/li&gt;
&lt;li&gt;Take related state — and the methods that operate on them — and create a composable for them (or better yet, create a store in Pinia)&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;reactive&lt;/code&gt; where you want to “reactify” some other JS object like a &lt;code&gt;Map&lt;/code&gt; or &lt;code&gt;Set&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;shallowRef&lt;/code&gt; and other more use-case-specific ref functions for any necessary edge cases.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Act 1: The differences between ref and reactive
&lt;/h2&gt;

&lt;p&gt;First, I want to take some time to specifically discuss how &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt; are different, and their different uses in general.&lt;/p&gt;

&lt;p&gt;I’ve tried to be exhaustive in this list. Of course, I’ve probably missed some things — please let me know if you know of something I haven’t included!&lt;/p&gt;

&lt;p&gt;With that out of the way, let’s look at some differences between these two tools we’ve been given.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dealing with .value
&lt;/h3&gt;

&lt;p&gt;The most obvious distinction between &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt; is that while &lt;code&gt;reactive&lt;/code&gt; quietly adds some magic to an object, &lt;code&gt;ref&lt;/code&gt; requires you to use the &lt;code&gt;value&lt;/code&gt; property:&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;reactiveObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;reactiveObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;refString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;new world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you see &lt;code&gt;something.value&lt;/code&gt; and you’re already familiar with how &lt;code&gt;ref&lt;/code&gt; works, it’s easy to understand at a glance that this is a reactive value. With a reactive object, this is not &lt;em&gt;necessarily&lt;/em&gt; as clear.&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;// Is this going to update reactively?&lt;/span&gt;
&lt;span class="c1"&gt;// It's impossible to know just from looking at this line&lt;/span&gt;
&lt;span class="nx"&gt;someObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New Value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Ah, this is likely a ref&lt;/span&gt;
&lt;span class="nx"&gt;someRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New Value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But here are some caveats:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you &lt;em&gt;don’t&lt;/em&gt; already understand how &lt;code&gt;ref&lt;/code&gt; works, seeing &lt;code&gt;.value&lt;/code&gt; means nothing to you. In fact, for someone new to the Composition API, &lt;code&gt;reactive&lt;/code&gt; is a much more intuitive API.&lt;/li&gt;
&lt;li&gt;It’s possible that non-reactive objects have a &lt;code&gt;value&lt;/code&gt; property. But because this clashes with the &lt;code&gt;ref&lt;/code&gt; API I would consider this an anti-pattern, whether or not you like using &lt;code&gt;ref&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is actually the difference that this entire debate hinges on — but we’ll get to that later.&lt;/p&gt;

&lt;p&gt;The important thing to remember for now is that using either &lt;code&gt;ref&lt;/code&gt; or &lt;code&gt;reactive&lt;/code&gt; requires us to access a property.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tooling and Syntax Sugar
&lt;/h3&gt;

&lt;p&gt;The main disadvantage of &lt;code&gt;ref&lt;/code&gt; here is that we have to write out these &lt;code&gt;.value&lt;/code&gt; accessors all over the place. It can get quite tedious!&lt;/p&gt;

&lt;p&gt;Fortunately, we have some extra tools that can help us mitigate this problem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Template unwrapping&lt;/li&gt;
&lt;li&gt;Watcher unwrapping&lt;/li&gt;
&lt;li&gt;Volar&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In many places Vue does this unwrapping of the &lt;code&gt;ref&lt;/code&gt; for us, so we don’t even need to add &lt;code&gt;.value&lt;/code&gt;. In the template we simply use the name of the &lt;code&gt;ref&lt;/code&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;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;{{ myRef }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Please put this on the screen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when using a watcher we specify the dependencies we want to be tracked, we can use a &lt;code&gt;ref&lt;/code&gt; directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This might change!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Vue automatically unwraps this ref for us&lt;/span&gt;
&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, the Volar VS Code extension will autocomplete refs for us, adding in that &lt;code&gt;.value&lt;/code&gt; wherever it’s needed. You can enable this in the settings under &lt;code&gt;Volar: Auto Complete Refs&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Fvolar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Fvolar.png" alt="Enabling .value auto-complete in Volar" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also enable it through the JSON settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"volar.autoCompleteRefs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is disabled by default to keep the CPU usage down.&lt;/p&gt;

&lt;h3&gt;
  
  
  ref uses reactive internally
&lt;/h3&gt;

&lt;p&gt;Here’s something interesting you may not have realized.&lt;/p&gt;

&lt;p&gt;When you use an object (including Arrays, Dates, etc.) with &lt;code&gt;ref&lt;/code&gt;, it’s actually calling &lt;code&gt;reactive&lt;/code&gt; under the hood.&lt;/p&gt;

&lt;p&gt;Anything that isn’t an object — a string, a number, a boolean value — and &lt;code&gt;ref&lt;/code&gt; uses its own logic.&lt;/p&gt;

&lt;p&gt;You can see it working in these two lines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/vuejs/core/blob/ce064a172b3b5bcb096b4984fe0c1a54177ac9c0/packages/reactivity/src/ref.ts#L113" rel="noopener noreferrer"&gt;Line 1&lt;/a&gt;: Creating a &lt;code&gt;ref&lt;/code&gt; involves calling &lt;code&gt;toReactive&lt;/code&gt; to get the internal value&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/vuejs/core/blob/ce064a172b3b5bcb096b4984fe0c1a54177ac9c0/packages/reactivity/src/reactive.ts#L251-L252" rel="noopener noreferrer"&gt;Line 2&lt;/a&gt;: &lt;code&gt;toReactive&lt;/code&gt; only calls &lt;code&gt;reactive&lt;/code&gt; if the passed value is an object
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Ref&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;uses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;reactive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;non-primitive&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;values&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;These&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;two&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;statements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;approximately&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;same&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;ref(&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;~=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ref(reactive(&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="err"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reassigning Values
&lt;/h3&gt;

&lt;p&gt;Vue developers for years have been tripped up by how reactivity works when reassigning values, especially with objects and arrays:&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;// You got a new array, awesome!&lt;/span&gt;
&lt;span class="c1"&gt;// ...but does it properly update your app?&lt;/span&gt;
&lt;span class="nx"&gt;myReactiveArray&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was a big issue with Vue 2 because of how the reactivity system worked. Vue 3 has &lt;em&gt;mostly&lt;/em&gt; solved this, but we’re still dealing with this issue when it comes to &lt;code&gt;reactive&lt;/code&gt; versus &lt;code&gt;ref&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You see, &lt;code&gt;reactive&lt;/code&gt; values cannot be reassigned how you’d expect:&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;myReactiveArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nf"&gt;watchEffect&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myReactiveArray&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// "[1, 2, 3]"&lt;/span&gt;

&lt;span class="nx"&gt;myReactiveArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// The watcher never fires&lt;/span&gt;
&lt;span class="c1"&gt;// We've replaced it with an entirely new, non-reactive object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is because the reference to the previous object is overwritten by the reference to the new object. We don’t keep that reference around anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The proxy-based reactivity system only works when we access properties on an object.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m going to repeat that because it’s such an important piece of the reactivity puzzle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reassigning values will not trigger the reactivity system. You &lt;em&gt;must&lt;/em&gt; modify a property on an existing object.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This also applies to refs, but this is made a little easier because of the standard &lt;code&gt;.value&lt;/code&gt; property that each &lt;code&gt;ref&lt;/code&gt; has:&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;myReactiveArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nf"&gt;watchEffect&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myReactiveArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// "[1, 2, 3]"&lt;/span&gt;

&lt;span class="nx"&gt;myReactiveArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// "[4, 5, 6]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt; are required to access a property to keep things reactive, so no real difference there.&lt;/p&gt;

&lt;p&gt;But, where this is the expected way of using a &lt;code&gt;ref&lt;/code&gt;, it’s not how you would &lt;em&gt;expect&lt;/em&gt; to use &lt;code&gt;reactive&lt;/code&gt;. It’s very easy to incorrectly use &lt;code&gt;reactive&lt;/code&gt; in this way and lose reactivity without realizing what’s happening.&lt;/p&gt;

&lt;h3&gt;
  
  
  Template Refs
&lt;/h3&gt;

&lt;p&gt;Reassigning values can also cause some issues when using the simplest form of template refs:&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;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"heading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;This is my page&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we can’t use a &lt;code&gt;reactive&lt;/code&gt; object at all:&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;heading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;watchEffect&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// "null"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the component is first instantiated, this will log out &lt;code&gt;null&lt;/code&gt;, because &lt;code&gt;heading&lt;/code&gt; has no value yet. But when the component is mounted and our &lt;code&gt;h1&lt;/code&gt; is created, it will not trigger. The &lt;code&gt;heading&lt;/code&gt; object becomes a new object, and our watcher loses track of it. The reference to the previous reactive object is overwritten.&lt;/p&gt;

&lt;p&gt;We need to use a &lt;code&gt;ref&lt;/code&gt; here:&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;heading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;watchEffect&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// "null"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, when the component is mounted it will log out the element. This is because only a &lt;code&gt;ref&lt;/code&gt; can be reassigned in this way.&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;is&lt;/em&gt; possible to use &lt;code&gt;reactive&lt;/code&gt; in this scenario, but it requires a bit of extra syntax using &lt;a href="https://vuejs.org/guide/essentials/template-refs.html#function-refs" rel="noopener noreferrer"&gt;function refs&lt;/a&gt;:&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="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"(el) =&amp;gt; { heading.element = el }"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is my page&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&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;Then our script would be written as so, using the &lt;code&gt;el&lt;/code&gt; property on our reactive object:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;heading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;el&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nf"&gt;watchEffect&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// "null"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Alex Vipond wrote a fantastic book on using the &lt;em&gt;function ref pattern&lt;/em&gt; to create highly reusable components in Vue (&lt;a href="https://michaelnthiessen.com/reusable-components" rel="noopener noreferrer"&gt;something I know quite a bit about&lt;/a&gt;). It’s eye-opening, and I’ve learned a ton from this book, so do yourself a favour and grab it here: &lt;a href="https://rethinking-reusability-in-vue.alexvipond.dev/" rel="noopener noreferrer"&gt;Rethinking Reusability in Vue&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Destructuring Values
&lt;/h3&gt;

&lt;p&gt;Destructuring a value from a &lt;code&gt;reactive&lt;/code&gt; object will break reactivity, since the reactivity comes from the object itself and not the property you’re grabbing:&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;myObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;prop2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prop1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myObj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// prop1 is just a plain String here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You must use &lt;code&gt;toRefs&lt;/code&gt; to convert all of the properties of the object into refs first, and then you can destructure without issues. This is because the reactivity is inherent to the &lt;code&gt;ref&lt;/code&gt; that you’re grabbing:&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;myObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;prop2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prop1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toRefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myObj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Now prop1 is a ref, maintaining reactivity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;toRefs&lt;/code&gt; in this way lets us destructure our props when using &lt;code&gt;script setup&lt;/code&gt; without losing reactivity:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prop1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prop2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toRefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;defineProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;prop1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;prop2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Composing ref and reactive
&lt;/h3&gt;

&lt;p&gt;One interesting pattern is combining &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt; together.&lt;/p&gt;

&lt;p&gt;We can take a bunch of refs and group them together inside of a &lt;code&gt;reactive&lt;/code&gt; object:&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;lettuce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;burger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// The ref becomes a property of the reactive object&lt;/span&gt;
  &lt;span class="nx"&gt;lettuce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// We can watch the reactive object&lt;/span&gt;
&lt;span class="nf"&gt;watchEffect&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;burger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lettuce&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// We can also watch the ref directly&lt;/span&gt;
&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lettuce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lettuce has changed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Updating the ref directly will trigger both watchers&lt;/span&gt;
  &lt;span class="c1"&gt;// This will log: `false`, 'lettuce has changed'&lt;/span&gt;
  &lt;span class="nx"&gt;lettuce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re able to use the &lt;code&gt;reactive&lt;/code&gt; object as we’d expect, but we can also reactively update the underlying refs even without accessing the &lt;code&gt;reactive&lt;/code&gt; object we’ve created. However you access the underlying properties, they reactively update everything else that’s “hooked up” to it.&lt;/p&gt;

&lt;p&gt;I’m not sure this pattern is better than simply putting a bunch of refs in a plain JS object, but it’s there if you need it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Organizing State with Ref and Reactive
&lt;/h3&gt;

&lt;p&gt;One of the best uses for &lt;code&gt;reactive&lt;/code&gt; is to manage state.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;reactive&lt;/code&gt; objects we can organize our state into objects instead of having a bunch of refs floating around:&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;// Just a bunch a refs :/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Michael&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Thiessen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;website&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;michaelnthiessen.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;twitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@MichaelThiessen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;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;michael&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Michael&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Thiessen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;website&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;michaelnthiessen.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;twitter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@MichaelThiessen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing around a single object instead of lots of refs is much easier, and helps to keep our code organized.&lt;/p&gt;

&lt;p&gt;There’s also the added benefit that it’s much more readable. When someone new comes to read this code, they know immediately that all of the values inside of a single &lt;code&gt;reactive&lt;/code&gt; object must be related somehow — otherwise, why would they be together?&lt;/p&gt;

&lt;p&gt;With a bunch a refs it’s much less clear as to how things are related and how they might work together (or not).&lt;/p&gt;

&lt;p&gt;However, an even better solution for grouping related pieces of reactive state might be to create a simple composable instead:&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;// Similar to defining a reactive object&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;michael&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;usePerson&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Michael&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Thiessen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;website&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;michaelnthiessen.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;twitter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@MichaelThiessen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// We usually return refs from composables, so we can destructure here&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;twitter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;michael&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives us the benefits of both worlds.&lt;/p&gt;

&lt;p&gt;Not only can we group our state together, but it’s even &lt;em&gt;more&lt;/em&gt; explicit that these are things that go together. And since we’re returning an object of refs from our composable (you’re doing that, right?) we can use each piece of state individually if we want.&lt;/p&gt;

&lt;p&gt;We have the added benefit that we can co-locate methods with our composable, too. So state changes and other business logic can be centralized and easier to manage.&lt;/p&gt;

&lt;p&gt;Of course, this may be a little more than what you need, in which case using &lt;code&gt;reactive&lt;/code&gt; is perfectly fine. You may also find yourself wondering, “why not just use Pinia for this?”, and you’d certainly have a valid point.&lt;/p&gt;

&lt;p&gt;The point is this:&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;reactive&lt;/code&gt; gives us another great option for organizing our state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping Non-Reactive Libraries and Objects
&lt;/h3&gt;

&lt;p&gt;In talking with Eduardo about this debate, he mentioned that the only time he uses &lt;code&gt;reactive&lt;/code&gt; is for wrapping collections (besides arrays):&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="kd"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;there&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&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;set&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;another one&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because Vue’s reactivity system uses proxies, this is a really easy way to take an existing object and spice it up with some reactivity.&lt;/p&gt;

&lt;p&gt;You can, of course, apply this to any other libraries that aren’t reactive. Though you may need to watch out for edge cases here and there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refactoring from Options API to Composition API
&lt;/h3&gt;

&lt;p&gt;It also appears that &lt;code&gt;reactive&lt;/code&gt; is really useful when refactoring a component to use the Composition API:&lt;/p&gt;


&lt;blockquote&gt;
&lt;p&gt;Transition from Vue2 is much easier if you go with reactive, especially if you have many options to update. You just copy and paste them and it works, yet if I have to choose - ref is the way :)&lt;/p&gt;— Plamen Zdravkov (&lt;a class="mentioned-user" href="https://dev.to/pa4ozdravkov"&gt;@pa4ozdravkov&lt;/a&gt;) &lt;a href="https://twitter.com/pa4oZdravkov/status/1613558580245823489?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;January 12, 2023&lt;/a&gt;
&lt;/blockquote&gt; 

&lt;p&gt;I haven’t tried this myself yet, but it does make sense. We don’t have anything like &lt;code&gt;ref&lt;/code&gt; in the Options API, but &lt;code&gt;reactive&lt;/code&gt; works very similarly to reactive properties inside of the &lt;code&gt;data&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;Here, we have a simple component that updates a field in component state using the Options API:&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="c1"&gt;// Options API&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Michael&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;superuser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;favouriteColour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;updateUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The simplest way to get this working using the Composition API is to copy and paste everything over using &lt;code&gt;reactive&lt;/code&gt;:&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="c1"&gt;// Composition API&lt;/span&gt;
&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Copy from data()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Michael&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;superuser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;favouriteColour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Copy from methods&lt;/span&gt;
  &lt;span class="nf"&gt;updateUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Use toRefs so we can access values directly&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;updateUsername&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;toRefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to make sure we change &lt;code&gt;this&lt;/code&gt; → &lt;code&gt;state&lt;/code&gt; when accessing reactive values, and remove it entirely if we need to access &lt;code&gt;updateUsername&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that it’s working, it’s much easier to continue refactoring using &lt;code&gt;ref&lt;/code&gt; if you want to. But the benefit of this approach is that it’s straightforward (possibly simple enough to automate with a codemod or something similar?).&lt;/p&gt;

&lt;h3&gt;
  
  
  They’re just different
&lt;/h3&gt;

&lt;p&gt;After going through all of these examples it should be pretty clear that &lt;em&gt;if we really had to,&lt;/em&gt; we could write perfectly fine Vue code with just &lt;code&gt;ref&lt;/code&gt; or just &lt;code&gt;reactive&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They’re equally capable — they’re just &lt;em&gt;different&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Keep this in mind as we explore the debate between &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep reading Act 2 and Act 3 of this article &lt;a href="https://michaelnthiessen.com/ref-vs-reactive/#act-2-the-ref-vs-reactive-debate" rel="noopener noreferrer"&gt;on my blog&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>productivity</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Fix the TypeScript intellisense template error in Vue</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Tue, 13 Sep 2022 15:16:04 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/how-to-fix-the-typescript-intellisense-template-error-in-vue-46eg</link>
      <guid>https://dev.to/michaelthiessen/how-to-fix-the-typescript-intellisense-template-error-in-vue-46eg</guid>
      <description>&lt;p&gt;I recently got this error while working on a Vue 3 project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;TypeScript intellisense is disabled on template. To &lt;span class="nb"&gt;enable&lt;/span&gt;, configure &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="s2"&gt;"jsx"&lt;/span&gt;: &lt;span class="s2"&gt;"preserve"&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;the &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="s2"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; property of tsconfig or jsconfig. To disable this prompt instead, configure &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="s2"&gt;"experimentalDisableTemplateSupport"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="s2"&gt;"vueCompilerOptions"&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; property.volar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No need to panic, just disable this Volar message &lt;a href="https://github.com/johnsoncodehk/volar/issues/1219#issuecomment-1104548432" rel="noopener noreferrer"&gt;exactly how it says&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;.tsconfig&lt;/code&gt; file you need to add &lt;code&gt;"jsx": "preserve"&lt;/code&gt; in the &lt;code&gt;compilerOptions&lt;/code&gt; section:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;compilerOptions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preserve&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’m using Nuxt 3, so my TypeScript config file looks a little different:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;https://v&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;.nuxtjs.org/concepts/typescript&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./.nuxt/tsconfig.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jsx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"preserve"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re using a &lt;a href="https://code.visualstudio.com/docs/languages/jsconfig#_jsconfig-options" rel="noopener noreferrer"&gt;jsconfig&lt;/a&gt; file instead, it may look closer to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"jsx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"preserve"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src/**/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;jsx&lt;/code&gt; option on the &lt;code&gt;.tsconfig&lt;/code&gt; &lt;a href="https://www.typescriptlang.org/tsconfig#jsx" rel="noopener noreferrer"&gt;controls how ts transforms and outputs&lt;/a&gt; &lt;code&gt;.tsx&lt;/code&gt; files, but this error happens on &lt;code&gt;.vue&lt;/code&gt; files with no &lt;code&gt;tsx&lt;/code&gt; extension.&lt;/p&gt;

&lt;p&gt;So changing this option to silence the warning has no real effect on our projects. In Vue we are only using TypeScript for type checking so this option doesn’t affect anything that we’re doing.&lt;/p&gt;

&lt;p&gt;This issue is likely happening because of the TypeScript Language Server that VS Code uses to provide the Intellisense feature. Volar hooks into this server, but unfortunately, has no control over it.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>typescript</category>
      <category>nuxt</category>
    </item>
    <item>
      <title>🔥 Vue Tips #31: The limitations of props</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Tue, 26 Oct 2021 15:14:51 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/vue-tips-31-the-limitations-of-props-36bh</link>
      <guid>https://dev.to/michaelthiessen/vue-tips-31-the-limitations-of-props-36bh</guid>
      <description>&lt;p&gt;&lt;em&gt;This newsletter was sent out to my list on October 20, 2021. &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; to get emails like this each week!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As always, here are some tips.&lt;/p&gt;

&lt;p&gt;Enjoy.&lt;/p&gt;

&lt;p&gt;— Michael&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Static and dynamic classes
&lt;/h2&gt;

&lt;p&gt;We can add static &lt;em&gt;and&lt;/em&gt; dynamic classes to an element at the same time:&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;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt;
    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"item in list"&lt;/span&gt;
    &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"item.id"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"always-here"&lt;/span&gt;
    &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"item.selected &amp;amp;&amp;amp; 'selected'"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {{ item.name }}
  &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you apply basic styling through static classes, and then dynamically add other styles as you need them.&lt;/p&gt;

&lt;p&gt;You can also achieve the same thing when using an &lt;code&gt;Object&lt;/code&gt; or &lt;code&gt;Array&lt;/code&gt; with dynamic classes:&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;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt;
    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"item in list"&lt;/span&gt;
    &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"item.id"&lt;/span&gt;
    &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"{
      'always-here': true,
      selected: item.selected,
    }"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {{ item.name }}
  &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with an &lt;code&gt;Array&lt;/code&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;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt;
    &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"item in list"&lt;/span&gt;
    &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"item.id"&lt;/span&gt;
    &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"[
      'always-here',
      item.selected &amp;amp;&amp;amp; 'selected',
    ]"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {{ item.name }}
  &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I prefer splitting them out into &lt;code&gt;class&lt;/code&gt; and &lt;code&gt;:class&lt;/code&gt; bindings though, since it makes the code clearer. It also makes it less likely to be broken when refactored!&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 The limitations of props
&lt;/h2&gt;

&lt;p&gt;Props are useful, but they have two glaring issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Impossible to pass markup*&lt;/li&gt;
&lt;li&gt;Not that flexible&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;*not technically impossible, but not something you want to do.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The solution to these two problems is the same, but we'll get there in a second.&lt;/p&gt;

&lt;p&gt;Many components you create are &lt;strong&gt;contentless components&lt;/strong&gt;. They provide a container, and you have to supply the content. Think of a button, a menu, an accordion, or a card component:&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;Card&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Shrimp Tempura"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"picOfShrimp.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Here are some words about tempura.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;How can you go wrong with fried food?&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"www.michaelnthiessen.com/shrimp-tempura"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Read more about Shrimp Tempura
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Card&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can often pass this content in as a regular &lt;code&gt;String&lt;/code&gt;. But many times you want to pass in a whole chunk of HTML, maybe even a component or two.&lt;/p&gt;

&lt;p&gt;You can't do that with props.*&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*again, yes, you could do this, but you'll definitely regret it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Props also require that you &lt;strong&gt;plan for all future use cases&lt;/strong&gt; of the component. If your &lt;code&gt;Button&lt;/code&gt; component only has two values for &lt;code&gt;type&lt;/code&gt;, you can't just use a third without modifying the &lt;code&gt;Button&lt;/code&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="c"&gt;&amp;lt;!-- You just have to believe it will work --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"AWESOME"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Button.vue&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// Unfortunately, 'AWESOME' doesn't work here :/&lt;/span&gt;
      &lt;span class="na"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secondary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;val&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm not a psychic, and I'm guessing you aren't either.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution to these problems?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think I gave it away with my card example above...&lt;/p&gt;

&lt;p&gt;..slots! 🎰&lt;/p&gt;

&lt;p&gt;Slots allow you to pass in whatever markup and components you want, and they also are fairly open-ended, giving you lots of flexibility. This is why in many cases, slots are simply better than props.&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 A photoshop plugin with Vue!?
&lt;/h2&gt;

&lt;p&gt;Last week I shared an article on creating a VS Code extension.&lt;/p&gt;

&lt;p&gt;Now we break out of the web world entirely, and see how we can create a plugin for Photoshop.&lt;/p&gt;

&lt;p&gt;I had no idea this was even possible!&lt;/p&gt;

&lt;p&gt;Read it now: &lt;a href="https://medium.com/adobetech/make-your-first-plugin-with-vue-js-for-photoshop-and-adobe-xd-7af094c69aa5" rel="noopener noreferrer"&gt;Make Your First Plugin with Vue JS for Photoshop and Adobe XD&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗞 Vue.js London is today + tomorrow!
&lt;/h2&gt;

&lt;p&gt;Quick, don't miss out on some amazing talks at &lt;a href="https://vuejs.london/" rel="noopener noreferrer"&gt;Vue.js Conference (London)&lt;/a&gt; — happening right now!&lt;/p&gt;

&lt;p&gt;Conferences are an amazing place to learn and connect with other Vue devs.&lt;/p&gt;

&lt;p&gt;We're slowly starting to see some more in-person events, along with lots of virtual ones too.&lt;/p&gt;

&lt;p&gt;Here are some upcoming conferences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.vuetoronto.com/" rel="noopener noreferrer"&gt;VueConf Toronto&lt;/a&gt; — November 22-23 — free + online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuejs.amsterdam/" rel="noopener noreferrer"&gt;Vuejs Global (Amsterdam)&lt;/a&gt; — February 10-11, 2022 — Amsterdam&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Let me know if I've missed any.)&lt;/p&gt;

&lt;h2&gt;
  
  
  💬 Brute force
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;When in doubt, use brute force. — Steve McConnell&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm often just not clever enough to come up with a clever solution.&lt;/p&gt;

&lt;p&gt;But cleverness isn't the point of software development.&lt;/p&gt;

&lt;p&gt;It's developing software &lt;em&gt;that works&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Spaced-repetition: 6 Levels of Reusability
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My course on &lt;a href="//michaelnthiessen.com/reusable-components"&gt;reusable components&lt;/a&gt; covers this framework, which outlines six different levels of reusability that you can use in your components.&lt;/p&gt;

&lt;p&gt;Here are the six levels of reusability:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Templating&lt;/strong&gt; — Reusing code by wrapping it up inside of a component&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration&lt;/strong&gt; — Using configuration props to allow for varying behaviour&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adaptability&lt;/strong&gt; — Allowing components to become future-proof&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inversion&lt;/strong&gt; — Letting other components control the process&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extension&lt;/strong&gt; — Using reusability throughout our component&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nesting&lt;/strong&gt; — Creating powerful hierarchies of components&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I cover this in more detail in &lt;a href="https://michaelnthiessen.com/6-levels-of-reusability" rel="noopener noreferrer"&gt;this excerpt from the course&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exclusive tips and insights every week
&lt;/h2&gt;

&lt;p&gt;Join 8335 other Vue devs and &lt;a href="//michaelnthiessen.com/newsletter"&gt;get exclusive tips and insights&lt;/a&gt; like these delivered straight to your inbox, every week.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have great content in your emails. I seriously learn something from every one of them. — Titus Decali&lt;/p&gt;

&lt;p&gt;Thanks for another beautiful tip 🙏 — Victor Onuoha&lt;/p&gt;

&lt;p&gt;Loving these, and the spaced repetition — Mark Goldstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="//michaelnthiessen.com/newsletter"&gt;Sign up here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔥 Vue Tips #30: Reusability Fundamentals: The Configuration Pattern</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Tue, 19 Oct 2021 15:26:53 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/vue-tips-30-reusability-fundamentals-the-configuration-pattern-2dkf</link>
      <guid>https://dev.to/michaelthiessen/vue-tips-30-reusability-fundamentals-the-configuration-pattern-2dkf</guid>
      <description>&lt;p&gt;&lt;em&gt;This newsletter was sent out to my list on October 13, 2021. &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; to get emails like this each week!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hey there,&lt;/p&gt;

&lt;p&gt;I'm still trying to adjust to the darkness this time of year in Canada.&lt;/p&gt;

&lt;p&gt;It's dark when I start work at 8, and dark again when I finish around 5. I work in my basement, so I don't get a lot of light during the day either.&lt;/p&gt;

&lt;p&gt;So I'm trying to take some time during the day to get outside and get some sunlight (and fresh air).&lt;/p&gt;

&lt;p&gt;Do you change your working habits throughout the year? A different schedule during winter or summer?&lt;/p&gt;

&lt;p&gt;— Michael&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 How I deal with dynamic classes
&lt;/h2&gt;

&lt;p&gt;A pattern I use constantly is triggering classes with &lt;code&gt;boolean&lt;/code&gt; flags:&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;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"disabled &amp;amp;&amp;amp; 'disabled-component'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Sometimes this component is disabled. Other times it isn't.
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Some styles */&lt;/span&gt;
&lt;span class="nc"&gt;.disabled-component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;darkgray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;not-allowed&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;Either the trigger is a prop I use directly, or a computed prop that tests for a specific condition:&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="nf"&gt;disabled&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isDisabled&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I just need one class on an element, I use the logical AND to trigger it:&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;div&lt;/span&gt; &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"disabled &amp;amp;&amp;amp; 'disabled-component'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes it's a decision between two classes, so I'll use a ternary:&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;div&lt;/span&gt;
  &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"disabled ? 'disabled-component' : 'not-yet-disabled'"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't often use more than two classes like this, but that's where an &lt;code&gt;Object&lt;/code&gt; or &lt;code&gt;Array&lt;/code&gt; comes in handy:&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;div&lt;/span&gt;
  &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"{
    primary: isPrimary,
    secondary: isSecondary,
    tertiary: isTertiary,
  }"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
  &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"[
    isPrimary &amp;amp;&amp;amp; 'primary',
    isSecondary &amp;amp;&amp;amp; 'secondary',
    isTertiary &amp;amp;&amp;amp; 'tertiary',
  ]"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, when it gets complex enough it's better to just have a computed prop that returns a string of class names (or returns an &lt;code&gt;Object&lt;/code&gt; or &lt;code&gt;Array&lt;/code&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;div&lt;/span&gt; &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"computedClasses"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔥 Reusability Fundamentals: The Configuration Pattern
&lt;/h2&gt;

&lt;p&gt;So you've got an awesome &lt;code&gt;CodeBlock&lt;/code&gt; component that does syntax highlighting, and even shows line numbers:&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;CodeBlock&lt;/span&gt; &lt;span class="na"&gt;language=&lt;/span&gt;&lt;span class="s"&gt;"js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  const myMessage = 'Highlighting code is supa ez';
&lt;span class="nt"&gt;&amp;lt;/CodeBlock&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But now you need to support a second color theme.&lt;/p&gt;

&lt;p&gt;Instead of copy and pasting (which is sometimes the right solution!), we can use props to help us create variations:&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="c"&gt;&amp;lt;!-- Uhhh, maybe not the best solution --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;DarkModeCodeBlock&lt;/span&gt; &lt;span class="na"&gt;language=&lt;/span&gt;&lt;span class="s"&gt;"js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  const myMessage = 'Highlighting code is supa ez';
&lt;span class="nt"&gt;&amp;lt;/DarkModeCodeBlock&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- This is what props were meant for --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;CodeBlock&lt;/span&gt;
  &lt;span class="na"&gt;language=&lt;/span&gt;&lt;span class="s"&gt;"js"&lt;/span&gt;
  &lt;span class="na"&gt;theme=&lt;/span&gt;&lt;span class="s"&gt;"darkMode"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  const myMessage = 'Highlighting code is supa ez';
&lt;span class="nt"&gt;&amp;lt;/CodeBlock&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You already do this intuitively, so this may not be a huge revelation.&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;the Configuration pattern is a fundamental pattern&lt;/strong&gt; — you can't ignore it if you want to master reusability.&lt;/p&gt;

&lt;p&gt;Dealing with prop explosions and understanding the Base Component Pattern are also part of mastering Configuration, the second level of reusability.&lt;/p&gt;

&lt;p&gt;And the other, more interesting levels of reusability?&lt;/p&gt;

&lt;p&gt;Well, mastering Configuration is vital to unlocking them. All the other levels build on top of this one.&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 Using Vue for a VS Code extension?
&lt;/h2&gt;

&lt;p&gt;This is a very interesting article on creating your own VS Code extension...&lt;/p&gt;

&lt;p&gt;But you get to build the UI using Vue.&lt;/p&gt;

&lt;p&gt;It goes into all the steps necessary to set up and get your extension running. From there, the sky is the limit (unless you're building rockets 🚀).&lt;/p&gt;

&lt;p&gt;Read it now: &lt;a href="https://www.codemag.com/article/2107071" rel="noopener noreferrer"&gt;Building a VS Code Extension Using Vue.js&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗞 Nuxt 3! Yeah, it's here!
&lt;/h2&gt;

&lt;p&gt;It was officially released yesterday, and comes with some amazing stuff:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vue 3&lt;/li&gt;
&lt;li&gt;Vite&lt;/li&gt;
&lt;li&gt;Typescript&lt;/li&gt;
&lt;li&gt;and so many other features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://nuxtjs.org/v3" rel="noopener noreferrer"&gt;Check it out here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, don't forget that &lt;a href="https://vuejs.london/" rel="noopener noreferrer"&gt;Vue.js London&lt;/a&gt; is happening next week!&lt;/p&gt;

&lt;h2&gt;
  
  
  💬 Repeated failure
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;As a rule, software systems do not work well until they have been used, and have failed repeatedly, in real applications. — Dave Parnas&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think Dave is talking about edge cases.&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;think&lt;/em&gt; you've covered them all, but you never have. Not until real users start using it for real.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Spaced-repetition: Reducing Objects
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;reduce&lt;/code&gt; function is really great for converting arrays into objects, but it can be intimidating.&lt;/p&gt;

&lt;p&gt;If we have a bunch of items that all have an &lt;code&gt;id&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can reorganize the array into an object, where the key for each item is the item's &lt;code&gt;id&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Grab the id from the item&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;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Add the item to our object&lt;/span&gt;
  &lt;span class="nx"&gt;prev&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Return the object so we can add more items&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prev&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;You get an object that looks 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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to group all objects in an array by a specific property, you can do something very similar:&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;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Grab the property from the item that we want to group by&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;prop&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Add a new array to the object if this is the first one&lt;/span&gt;
  &lt;span class="c1"&gt;// with this value&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Add our item to this array&lt;/span&gt;
  &lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Return the object so we can add more items&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prev&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;Our final object looks 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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exclusive tips and insights every week
&lt;/h2&gt;

&lt;p&gt;Join 8335 other Vue devs and &lt;a href="//michaelnthiessen.com/newsletter"&gt;get exclusive tips and insights&lt;/a&gt; like these delivered straight to your inbox, every week.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have great content in your emails. I seriously learn something from every one of them. — Titus Decali&lt;/p&gt;

&lt;p&gt;Thanks for another beautiful tip 🙏 — Victor Onuoha&lt;/p&gt;

&lt;p&gt;Loving these, and the spaced repetition — Mark Goldstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="//michaelnthiessen.com/newsletter"&gt;Sign up here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔥 Vue Tips #29: Component Seams Framework: The easy way to split up components</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Tue, 12 Oct 2021 16:00:14 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/vue-tips-29-component-seams-framework-the-easy-way-to-split-up-components-1j8k</link>
      <guid>https://dev.to/michaelthiessen/vue-tips-29-component-seams-framework-the-easy-way-to-split-up-components-1j8k</guid>
      <description>&lt;p&gt;&lt;em&gt;This newsletter was sent out to my list on October 6, 2021. &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; to get emails like this each week!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Heyo,&lt;/p&gt;

&lt;p&gt;Do you like hot sauce?&lt;/p&gt;

&lt;p&gt;Well, I tried making some last week, and it was an utter failure. So I'll stick with baking bread.&lt;/p&gt;

&lt;p&gt;And if you don't like hot sauce, maybe you'll enjoy these hot tips instead.&lt;/p&gt;

&lt;p&gt;— Michael&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 v-pre and v-once
&lt;/h2&gt;

&lt;p&gt;If you've got large chunks of static or mostly static content, you can tell Vue to ignore it using the &lt;code&gt;v-pre&lt;/code&gt; or &lt;code&gt;v-once&lt;/code&gt; directives:&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;template&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- These elements never change --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-pre&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Bananas for sale 🍌&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      Come get this wonderful fruit!
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      Our bananas are always the same price — $1 each!
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"rounded p-4 bg-yellow-200 text-black"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;
        Number of bananas in stock: as many as you need
      &lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
        That's right, we never run out of bananas!
      &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
      Some people might say that we're... bananas about bananas!
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These can be useful performance optimizations if you need them.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;v-pre&lt;/code&gt; Vue will treat the element and it's children as static HTML, and won't do any of it's magic on it. The &lt;code&gt;v-once&lt;/code&gt; directive tells Vue to evaluate it once, and then never update it again.&lt;/p&gt;

&lt;p&gt;Here are the docs for &lt;a href="https://v3.vuejs.org/api/directives.html#v-pre" rel="noopener noreferrer"&gt;v-pre&lt;/a&gt; and &lt;a href="https://v3.vuejs.org/api/directives.html#v-once" rel="noopener noreferrer"&gt;v-once&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Component Seams Framework: The easy way to split up components
&lt;/h2&gt;

&lt;p&gt;Here's a technique for splitting up components:&lt;/p&gt;

&lt;p&gt;The code you write forms natural groups. You want to identify these groups, and the seams that run between them.&lt;/p&gt;

&lt;p&gt;Once you do that, it's easy to extract components — by keeping things in their natural groups as much as possible.&lt;/p&gt;

&lt;p&gt;The Component Seams Framework helps you do that in just three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Find the seams&lt;/strong&gt; — they can be found in your template, by looking for &lt;em&gt;repeated sections&lt;/em&gt;, as well as sections that &lt;em&gt;perform different tasks&lt;/em&gt;. You can also find them in your props, state, and computed props, by looking for things that are &lt;em&gt;related&lt;/em&gt; and are often &lt;em&gt;updated together&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stack the seams&lt;/strong&gt; — take all of the seams you've found, line them up, and you'll start to see where they agree (and where they don't).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split along the seams&lt;/strong&gt; — piece by piece, we'll pull things out and then figure out what to do with its dependencies. Either &lt;em&gt;include the dependency&lt;/em&gt; in the new component or &lt;em&gt;pass it in&lt;/em&gt; to the new component somehow (prop, slot, or event).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This method is covered in more detail in &lt;a href="//michaelnthiessen.com/clean-components"&gt;Clean Components&lt;/a&gt; if you want to learn more.&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 25 Vue Tips You Need to Know
&lt;/h2&gt;

&lt;p&gt;I've written 58 Vue tips so far this year for you.&lt;/p&gt;

&lt;p&gt;That's 2 every week for 29 weeks (since March 22).&lt;/p&gt;

&lt;p&gt;I put 25 of them together for you in this one article (which is one of the top Vue posts of all time on DEV.to).&lt;/p&gt;

&lt;p&gt;Read it now: &lt;a href="https://dev.to/michaelthiessen/25-vue-tips-you-need-to-know-2h70"&gt;25 Vue Tips You Need to Know&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗞 Nuxt 3 is nuxt week!
&lt;/h2&gt;

&lt;p&gt;It's coming October 12.&lt;/p&gt;

&lt;p&gt;This is going to be huge, and I can't wait to try it out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vue 3&lt;/li&gt;
&lt;li&gt;Vite&lt;/li&gt;
&lt;li&gt;Typescript&lt;/li&gt;
&lt;li&gt;and so many other features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://nuxtjs.org/v3" rel="noopener noreferrer"&gt;Learn more about what's coming with Nuxt 3&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  💬 The real problem
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Sometimes the problem is to discover what the problem is. — Gordon Glegg&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've wasted so much of my life trying to solve things that weren't actually problems.&lt;/p&gt;

&lt;p&gt;Now I try to make sure that what I think is the problem is &lt;em&gt;actually&lt;/em&gt; the problem.&lt;/p&gt;

&lt;p&gt;It saves me so much time and effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Spaced-repetition: Master computed props
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a function does more than just return a value, it makes your code more complicated.&lt;/p&gt;

&lt;p&gt;These are called &lt;a href="https://michaelnthiessen.com/side-effect-surgery" rel="noopener noreferrer"&gt;side effects&lt;/a&gt;, and you should never have them inside of a computed prop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchUserInformation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Side effect&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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;However, fixing this is quite straightforward. We can just move that side effect into a watcher that is triggered whenever the computed prop updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fullName&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchUserInformation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Side effect&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This applies equally to the composition API, although the syntax is slightly different.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At first glance, this may seem like we made the code more complicated. But actually, we've made it a &lt;a href="https://michaelnthiessen.com/side-effect-surgery" rel="noopener noreferrer"&gt;lot simpler&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This concept is expanded on in my course, &lt;a href="https://michaelnthiessen.com/clean-components" rel="noopener noreferrer"&gt;Clean Components&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exclusive tips and insights every week
&lt;/h2&gt;

&lt;p&gt;Join 8335 other Vue devs and &lt;a href="//michaelnthiessen.com/newsletter"&gt;get exclusive tips and insights&lt;/a&gt; like these delivered straight to your inbox, every week.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have great content in your emails. I seriously learn something from every one of them. — Titus Decali&lt;/p&gt;

&lt;p&gt;Thanks for another beautiful tip 🙏 — Victor Onuoha&lt;/p&gt;

&lt;p&gt;Loving these, and the spaced repetition — Mark Goldstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="//michaelnthiessen.com/newsletter"&gt;Sign up here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔥 Vue Tips #28: Easily create component variations with the Base Component pattern</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Tue, 05 Oct 2021 13:45:02 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/vue-tips-28-easily-create-component-variations-with-the-base-component-pattern-4h1p</link>
      <guid>https://dev.to/michaelthiessen/vue-tips-28-easily-create-component-variations-with-the-base-component-pattern-4h1p</guid>
      <description>&lt;p&gt;&lt;em&gt;This newsletter was sent out to my list on September 29, 2021. &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; to get emails like this each week!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What's up?&lt;/p&gt;

&lt;p&gt;You may have noticed that recently I've been experimenting with adding sponsors to this newsletter.&lt;/p&gt;

&lt;p&gt;Honestly, I'm not sure I like putting them in here.&lt;/p&gt;

&lt;p&gt;It's extra work that I don't particularly enjoy, and I have the feeling it doesn't make the newlsetter better for you either. Of course, if it made boatloads of cash so I could focus more time on this then it would be worth it, but that's just not the case...&lt;/p&gt;

&lt;p&gt;I'd rather spend that time on writing better tips for you.&lt;/p&gt;

&lt;p&gt;— Michael&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Directly accessing parent components (and why)
&lt;/h2&gt;

&lt;p&gt;Props down, events up. That's how your components should communicate — most of the time.&lt;/p&gt;

&lt;p&gt;But in &lt;em&gt;rare cases&lt;/em&gt;, that just doesn't work.&lt;/p&gt;

&lt;p&gt;If you need direct access to the parent component, you can use the instance property &lt;code&gt;$parent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Tight coupling like this is usually a bad idea&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methodOnParentComponent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also get direct access to the application root, the very top-most component in the tree, by using &lt;code&gt;$root&lt;/code&gt;. Vue 2 also has &lt;code&gt;$children&lt;/code&gt;, but it was taken out for Vue 3 (please don't use this one).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When would these be useful?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are a few different scenarios I can think of. Usually when you want to abstract some behaviour and have it work "magically" behind the scenes.&lt;/p&gt;

&lt;p&gt;In those cases, you don't want to use props and events to connect up a component. Rather, you use &lt;code&gt;provide&lt;/code&gt;/&lt;code&gt;inject&lt;/code&gt;, &lt;code&gt;$parent&lt;/code&gt;, or &lt;code&gt;$root&lt;/code&gt;, to &lt;em&gt;automatically&lt;/em&gt; connect the components and make things happen.&lt;/p&gt;

&lt;p&gt;But it's hard to come up with an example where this is the best solution. Using &lt;code&gt;provide&lt;/code&gt;/&lt;code&gt;inject&lt;/code&gt; is almost always the better choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Easily create component variations with the Base Component pattern
&lt;/h2&gt;

&lt;p&gt;The Base Component pattern is one of my favourite ways to make lots of different versions and variants from a single component.&lt;/p&gt;

&lt;p&gt;It has a few basic steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create your base component&lt;/li&gt;
&lt;li&gt;Wrap it with another component to get a variant of the original&lt;/li&gt;
&lt;li&gt;Repeat step 2 as many times as you need&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's an example, creating a &lt;code&gt;DisabledButton&lt;/code&gt; variant out of a &lt;code&gt;BaseButton&lt;/code&gt; component:&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="c"&gt;&amp;lt;!-- DisabledButton.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Never forget how to create this disabled button.
       Package it up using the Base Component pattern. --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;BaseButton&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"disabled"&lt;/span&gt;
    &lt;span class="na"&gt;disabled&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- You can't accidentally use the wrong icon now.
         It's provided here for you --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#icon&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Icon&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"disabled"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/BaseButton&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use this pattern in many different ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lock down props&lt;/strong&gt; — take a &lt;code&gt;Button&lt;/code&gt; component and hard code a few props to get a &lt;code&gt;DisabledButton&lt;/code&gt;. Now you can just use the &lt;code&gt;DisabledButton&lt;/code&gt; directly without having to fiddle with all the necessary props each time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lock down slots&lt;/strong&gt; — create an &lt;code&gt;InfoButton&lt;/code&gt; variant where the icon passed to the &lt;code&gt;Button&lt;/code&gt; is always the same. Now, if you ever need to change the icon (or anything else) you can do it in one place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplify props&lt;/strong&gt; — sometimes components end up with dozens of props, most of which are for edge cases. Create a &lt;code&gt;BaseButton&lt;/code&gt; with all the props, and a &lt;code&gt;Button&lt;/code&gt; that passes on only the most common ones. This is a lot safer, easier to use, and the documentation is easier to read too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've included more on this pattern in &lt;a href="//michaelnthiessen.com/reusable-components"&gt;Reusable Components&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 How do you structure a Vue project?
&lt;/h2&gt;

&lt;p&gt;Just an hour ago, Marco asked me this very question.&lt;/p&gt;

&lt;p&gt;My quick response was: keep it flat and simple, and when things start to get messy, slowly add in folders.&lt;/p&gt;

&lt;p&gt;An even better response: Markus wrote a great article on this, and he goes into much more detail and provides some more specific advice.&lt;/p&gt;

&lt;p&gt;Read his article here: &lt;a href="https://markus.oberlehner.net/blog/vue-project-directory-structure-keep-it-flat-or-group-by-domain/" rel="noopener noreferrer"&gt;Vue Project Directory Structure&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💬 Software Quote
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Automating chaos just gives faster chaos. — Mark Fewster&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the paradox of abstraction:&lt;/p&gt;

&lt;p&gt;Creating a component and reusing it over and over can save you a lot of time.&lt;/p&gt;

&lt;p&gt;But if that component is wrong or has a bug, you also multiply that problem over and over 🤦‍♂️&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Spaced-repetition: Aria roles you didn't know you needed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Aria roles are used to tell a screenreader what an element is for.&lt;/p&gt;

&lt;p&gt;This is really important when the native HTML elemen just doesn't exist (eg. roles like &lt;code&gt;toolbar&lt;/code&gt; and &lt;code&gt;alert&lt;/code&gt;) or when you're using a different HTML element for design or technical reasons (eg. wrapping a &lt;code&gt;radio&lt;/code&gt; button to style it).&lt;/p&gt;

&lt;p&gt;But please, remember that you should always use the semantic element where you can. This is always the best and most effective solution.&lt;/p&gt;

&lt;p&gt;There are six different categories of aria roles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Widget - roles like &lt;code&gt;button&lt;/code&gt;, &lt;code&gt;checkbox&lt;/code&gt;, &lt;code&gt;separator&lt;/code&gt;, &lt;code&gt;tab&lt;/code&gt;, or &lt;code&gt;scrollbar&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Composite - roles like &lt;code&gt;combobox&lt;/code&gt; and &lt;code&gt;listbox&lt;/code&gt; (these are for dropdown menus), &lt;code&gt;radiogroup&lt;/code&gt;, or &lt;code&gt;tree&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Document structure - this includes &lt;code&gt;article&lt;/code&gt;, &lt;code&gt;presentation&lt;/code&gt;, &lt;code&gt;figure&lt;/code&gt;, &lt;code&gt;feed&lt;/code&gt;, and &lt;code&gt;directory&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Landmark - &lt;code&gt;banner&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;navigation&lt;/code&gt;, and &lt;code&gt;region&lt;/code&gt; are roles in this category&lt;/li&gt;
&lt;li&gt;Live region - &lt;code&gt;alert&lt;/code&gt;, &lt;code&gt;log&lt;/code&gt;, &lt;code&gt;marquee&lt;/code&gt;, and &lt;code&gt;status&lt;/code&gt; are roles that might update with real-time information&lt;/li&gt;
&lt;li&gt;Window - &lt;code&gt;alertdialog&lt;/code&gt; and &lt;code&gt;dialog&lt;/code&gt; are the only two roles in this category&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can check out the full list here: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#roles" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#roles&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exclusive tips and insights every week
&lt;/h2&gt;

&lt;p&gt;Join 8135 other Vue devs and &lt;a href="//michaelnthiessen.com/newsletter"&gt;get exclusive tips and insights&lt;/a&gt; like these delivered straight to your inbox, every week.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have great content in your emails. I seriously learn something from every one of them. — Titus Decali&lt;/p&gt;

&lt;p&gt;Thanks for another beautiful tip 🙏 — Victor Onuoha&lt;/p&gt;

&lt;p&gt;Loving these, and the spaced repetition — Mark Goldstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="//michaelnthiessen.com/newsletter"&gt;Sign up here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔥 Vue Tips #27: Controlled Props — or How to Override Internal State</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Wed, 29 Sep 2021 15:42:59 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/27-controlled-props-or-how-to-override-internal-state-2gm9</link>
      <guid>https://dev.to/michaelthiessen/27-controlled-props-or-how-to-override-internal-state-2gm9</guid>
      <description>&lt;p&gt;&lt;em&gt;This newsletter was sent out to my list on September 22, 2021. &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; to get emails like this each week!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hi!&lt;/p&gt;

&lt;p&gt;First, I need to say a huge THANK YOU to all 212 of you who bought Clean Components in the sale that ended last week.&lt;/p&gt;

&lt;p&gt;Your support of my work is absolutely astonishing — it's what gives me the motivation to keep creating.&lt;/p&gt;

&lt;p&gt;So, it's officially the first day of fall, at least in the northern hemisphere.&lt;/p&gt;

&lt;p&gt;Everything seems to be pumpkin-spiced these days:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lattes from Starbucks&lt;/li&gt;
&lt;li&gt;scented candles (why)&lt;/li&gt;
&lt;li&gt;Cheerios (okay, I'm willing to try that one)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please tell me this pumpkin obsession is just a North American thing?&lt;/p&gt;

&lt;p&gt;I'll spare you from pumpkin-spiced tips though. These ones are just the regular kind 🎃&lt;/p&gt;

&lt;p&gt;— Michael&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Controlled Props — or How to Override Internal State
&lt;/h2&gt;

&lt;p&gt;Here we have a simple &lt;code&gt;Toggle&lt;/code&gt; component that can show or hide content:&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;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Toggle&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Toggled Content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    This content can be hidden by clicking on the toggle.
  &lt;span class="nt"&gt;&amp;lt;/Toggle&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It keeps track of its own &lt;code&gt;open&lt;/code&gt; state internally right now.&lt;/p&gt;

&lt;p&gt;But what if we want to override that internal state, but only &lt;em&gt;some of the time&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;To do this we have to dynamically switch between relying on props and events, and relying on internal state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Toggle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// Must be set to `undefined` and not `false`&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Internal state&lt;/span&gt;
      &lt;span class="na"&gt;_hidden&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;toggleHidden&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Switch between emitting an event and toggling state&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hidden&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toggle-hidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_hidden&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;$hidden&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Dynamically switch between state or prop&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hidden&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hidden&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;Toggle&lt;/code&gt; component we now have to use the &lt;code&gt;$hidden&lt;/code&gt; computed prop:&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;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;
      &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"toggleHidden"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      {{ title }}
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"$hidden"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check out a &lt;a href="https://michaelnthiessen.com/controlled-props-pattern" rel="noopener noreferrer"&gt;more detailed tutorial on my blog&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Computed Props in Your Template: v-memo
&lt;/h2&gt;

&lt;p&gt;Vue 3.2 gives you fine-grained control over template re-rendering using &lt;code&gt;v-memo&lt;/code&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;div&lt;/span&gt; &lt;span class="na"&gt;v-memo=&lt;/span&gt;&lt;span class="s"&gt;"[varA, varB, varC]"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works much the same as a computed prop does. An element with &lt;code&gt;v-memo&lt;/code&gt; is only re-rendered when the array changes, but otherwise it caches (or memoizes) the result.&lt;/p&gt;

&lt;p&gt;When it's used with &lt;code&gt;v-for&lt;/code&gt; you can selectively re-render only the parts of a list that have changed:&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;div&lt;/span&gt;
  &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"item in list"&lt;/span&gt;
  &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"item.id"&lt;/span&gt;
  &lt;span class="na"&gt;v-memo=&lt;/span&gt;&lt;span class="s"&gt;"[item.id === selected]"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we only update the nodes that went selected to unselected, or vice versa. Much faster if you're dealing with extremely long lists!&lt;/p&gt;

&lt;p&gt;But since Vue is already so efficient with re-renders, you shouldn't need to use &lt;code&gt;v-memo&lt;/code&gt; very often.&lt;/p&gt;

&lt;p&gt;It's definitely a useful tool to help you get more performance — when you really need it.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://v3.vuejs.org/api/directives.html#v-memo" rel="noopener noreferrer"&gt;the docs for v-memo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 (Sponsored) Come work with me at Vidyard
&lt;/h2&gt;

&lt;p&gt;It's where I've learned all that I know about Vue.&lt;/p&gt;

&lt;p&gt;We're rapidly growing our remote engineering team and we need intermediate and senior devs in Canada and the US.&lt;/p&gt;

&lt;p&gt;Our stack is Vue + GraphQL + Rails (with React, Node, and some other things, too).&lt;/p&gt;

&lt;p&gt;You'll get to work on tons of diverse and interesting projects. Some of the things I've worked on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In-house component library — written in Vue, of couse&lt;/li&gt;
&lt;li&gt;Analytics dashboard and pipeline — lots of data, charts, and microservices&lt;/li&gt;
&lt;li&gt;That time we &lt;strong&gt;rewrote our entire frontend in Vue&lt;/strong&gt; — yes, we're &lt;em&gt;very&lt;/em&gt; committed to paying down tech debt&lt;/li&gt;
&lt;li&gt;UI for simple video editing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's also the best place to work (in my opinion):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In 4 years I've never had to rush to hit a deadline. No evenings, weekends, or stress-induced baldness.&lt;/li&gt;
&lt;li&gt;Every dev has their own "sandbox" — a replica of our production environment, running in AWS, complete with hot reloading.&lt;/li&gt;
&lt;li&gt;The fundamentals: continuous deployment, e2e testing, mentors that help you grow, a focus on doing things &lt;em&gt;right&lt;/em&gt;, very few meetings to interrupt your flow, too many memes, never enough memes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.vidyard.com/careers/#positions" rel="noopener noreferrer"&gt;Apply now and get the best job you've ever had.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 I didn't know this about computed props
&lt;/h2&gt;

&lt;p&gt;Computed props may not work &lt;em&gt;exactly&lt;/em&gt; how you think they do.&lt;/p&gt;

&lt;p&gt;That's what a lot of us are finding out after reading Thorsten's post on a common misconception around rendering and computed props.&lt;/p&gt;

&lt;p&gt;It's not something you'll run into every day, but it's good to know about if you run into performance problems.&lt;/p&gt;

&lt;p&gt;Read it here: &lt;a href="https://dev.to/linusborg/vue-when-a-computed-property-can-be-the-wrong-tool-195j"&gt;When a computed property can be the wrong tool&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💬 Working
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The greatest performance improvement of all is when a system goes from not-working to working. — John Ousterhout&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First, get it to work. Then get it to work well. Don't worry about how good the code is until it's working — that's what refactoring is for.&lt;/p&gt;

&lt;p&gt;It's &lt;em&gt;so much easier&lt;/em&gt; to transform bad code into good code if it's already working correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  🗞 News: Vue.js Amsterdam update
&lt;/h2&gt;

&lt;p&gt;Unfortunately, Vue.js Amsterdam &lt;a href="https://twitter.com/vuejsamsterdam/status/1437687577667121156?s=20" rel="noopener noreferrer"&gt;had to cancel&lt;/a&gt; their conference for this October due to COVID, but it's on for February 2022!&lt;/p&gt;

&lt;p&gt;Here are some upcoming conferences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://vuejs.london/" rel="noopener noreferrer"&gt;Vue.js Conference (London)&lt;/a&gt; — October 20-21 — London and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuetoronto.com/" rel="noopener noreferrer"&gt;VueConf Toronto&lt;/a&gt; — November 22-23 — free + online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuejs.amsterdam/" rel="noopener noreferrer"&gt;Vuejs Global (Amsterdam)&lt;/a&gt; — February 10-11, 2022 — Amsterdam&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧠 Spaced-repetition: Where do you put shared state?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's say we have a &lt;code&gt;Button&lt;/code&gt; component that toggles an &lt;code&gt;Accordion&lt;/code&gt; open and closed by changing the variable &lt;code&gt;isOpen&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the &lt;code&gt;Button&lt;/code&gt; component changes it's text between "Show" and "Hide" based on the same variable, &lt;code&gt;isOpen&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// Parent.vue
&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- Both components need access to `isOpen`  --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Button&lt;/span&gt; &lt;span class="na"&gt;:is-open=&lt;/span&gt;&lt;span class="s"&gt;"isOpen"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"toggleOpen"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Accordion&lt;/span&gt; &lt;span class="na"&gt;:is-open=&lt;/span&gt;&lt;span class="s"&gt;"isOpen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Some interesting content in here.
  &lt;span class="nt"&gt;&amp;lt;/Accordion&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two sibling components (because they are beside each other) need access to the same state, so where do we put it?&lt;/p&gt;

&lt;p&gt;Answer: The lowest common ancestor!&lt;/p&gt;

&lt;p&gt;Which, in this case, is the parent of both components.&lt;/p&gt;

&lt;p&gt;Because state only flows down through props, shared state &lt;em&gt;must&lt;/em&gt; be in a common ancestor. And we also want to keep state as close as possible, so we put it in the &lt;em&gt;lowest&lt;/em&gt; common ancestor.&lt;/p&gt;

&lt;p&gt;While this example may seem obvious to some, when the components sharing state are in separate components, in separate folders, it's harder to see that this is the solution.&lt;/p&gt;

&lt;p&gt;Note: we also want to co-locate state with the logic that modifies it, so we have to put the &lt;code&gt;toggleOpen&lt;/code&gt; method in the parent as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exclusive tips and insights every week
&lt;/h2&gt;

&lt;p&gt;Join 8135 other Vue devs and &lt;a href="//michaelnthiessen.com/newsletter"&gt;get exclusive tips and insights&lt;/a&gt; like these delivered straight to your inbox, every week.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have great content in your emails. I seriously learn something from every one of them. — Titus Decali&lt;/p&gt;

&lt;p&gt;Thanks for another beautiful tip 🙏 — Victor Onuoha&lt;/p&gt;

&lt;p&gt;Loving these, and the spaced repetition — Mark Goldstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="//michaelnthiessen.com/newsletter"&gt;Sign up here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔥 Vue Tips #26: 6 levels of component reusability</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Mon, 20 Sep 2021 14:49:37 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/vue-tips-26-6-levels-of-component-reusability-36l3</link>
      <guid>https://dev.to/michaelthiessen/vue-tips-26-6-levels-of-component-reusability-36l3</guid>
      <description>&lt;p&gt;&lt;em&gt;This newsletter was sent out to my list on September 15, 2021. &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; to get emails like this each week!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Heyo,&lt;/p&gt;

&lt;p&gt;Nuxt Nation is happening today (maybe &lt;em&gt;right now&lt;/em&gt; depending on when you open this email).&lt;/p&gt;

&lt;p&gt;You might still be able to catch some of the action: &lt;a href="https://nuxtnation.com/" rel="noopener noreferrer"&gt;Nuxt Nation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the meantime, here are some more tips for ya.&lt;/p&gt;

&lt;p&gt;— Michael&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 6 Levels of Reusability
&lt;/h2&gt;

&lt;p&gt;My course on &lt;a href="//michaelnthiessen.com/reusable-components"&gt;reusable components&lt;/a&gt; covers this framework, which outlines six different levels of reusability that you can use in your components.&lt;/p&gt;

&lt;p&gt;Here are the six levels of reusability:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Templating&lt;/strong&gt; — Reusing code by wrapping it up inside of a component&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration&lt;/strong&gt; — Using configuration props to allow for varying behaviour&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adaptability&lt;/strong&gt; — Allowing components to become future-proof&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inversion&lt;/strong&gt; — Letting other components control the process&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extension&lt;/strong&gt; — Using reusability throughout our component&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nesting&lt;/strong&gt; — Creating powerful hierarchies of components&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I cover this in more detail in &lt;a href="https://michaelnthiessen.com/6-levels-of-reusability" rel="noopener noreferrer"&gt;this excerpt from the course&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Grid Template Areas
&lt;/h2&gt;

&lt;p&gt;Sometimes complicated layouts are, well, complicated. But using &lt;code&gt;grid-template-areas&lt;/code&gt; is here to help!&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;section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;Page header&lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;Nav bar&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;Content goes here!&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;Not for your feet&lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this HTML, you'd first attach &lt;code&gt;grid-area&lt;/code&gt; names to each element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;footer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can describe your layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... some other CSS grid set up here */&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-areas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"header header"&lt;/span&gt;
                       &lt;span class="s1"&gt;"nav    main"&lt;/span&gt;
                       &lt;span class="s1"&gt;"footer footer"&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;And if you need a single column layout for mobile (with the nav at the bottom, just for fun):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-areas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"header"&lt;/span&gt;
                       &lt;span class="s1"&gt;"main"&lt;/span&gt;
                       &lt;span class="s1"&gt;"nav"&lt;/span&gt;
                       &lt;span class="s1"&gt;"footer"&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;It's pretty easy to see exactly how the page is being laid out with &lt;code&gt;grid-template-areas&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 Helpful Patterns in Vue
&lt;/h2&gt;

&lt;p&gt;Although I disagree with using custom elements to get a flatter component hierarchy, Brennan has a bunch of useful tips and patterns in this article.&lt;/p&gt;

&lt;p&gt;I use the loading state one all the time.&lt;/p&gt;

&lt;p&gt;Read it here: &lt;a href="https://dev.to/jfbrennan/helpful-patterns-i-use-in-vue-539i"&gt;Helpful Patterns I Use in Vue&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗞 News: Nuxt Nation is TODAY
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nuxtnation.com/" rel="noopener noreferrer"&gt;Don't miss it!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also have three more conferences coming up in the next 2 months, all accessible online and two offering (limited) in-person experiences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.vuejs.amsterdam/" rel="noopener noreferrer"&gt;Vuejs Global (Amsterdam)&lt;/a&gt; — October 1st and 4th — Amsterdam and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.london/" rel="noopener noreferrer"&gt;Vue.js Conference (London)&lt;/a&gt; — October 20-21 — London and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuetoronto.com/" rel="noopener noreferrer"&gt;VueConf Toronto&lt;/a&gt; — November 22-23 — free + online&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💬 Two Types of Languages
&lt;/h2&gt;

&lt;p&gt;"There are only two kinds of languages: the ones people complain about and the ones nobody uses." — Bjarne Stroustrup&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Spaced-repetition: Vue Testing Library
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of my favourite tools for testing is &lt;a href="https://testing-library.com/docs/vue-testing-library/intro/" rel="noopener noreferrer"&gt;Vue Testing Library&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;displays correct text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByText&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Fail the test if this text doesn't exist/&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;It builds on top of &lt;code&gt;vue-test-utils&lt;/code&gt;, making it easier to write tests that are closer to how users actually interact with your app.&lt;/p&gt;

&lt;p&gt;Users look for specific text, or look for a button to click. They don't look for the &lt;code&gt;nth child of a div with the class .booking-card-container&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Writing tests this way makes them easier to understand, simpler to write, and more robust against changes to your code. Nothing about this test is concerned with the implementation, so it's unlikely to break even under a heavy refactor.&lt;/p&gt;

&lt;p&gt;If this idea is new to you, I highly encourage you to read more about the Testing Library &lt;a href="https://testing-library.com/docs/guiding-principles" rel="noopener noreferrer"&gt;guiding principles&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exclusive tips and insights every week
&lt;/h2&gt;

&lt;p&gt;Join 8135 other Vue devs and &lt;a href="//michaelnthiessen.com/newsletter"&gt;get exclusive tips and insights&lt;/a&gt; like these delivered straight to your inbox, every week.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have great content in your emails. I seriously learn something from every one of them. — Titus Decali&lt;/p&gt;

&lt;p&gt;Thanks for another beautiful tip 🙏 — Victor Onuoha&lt;/p&gt;

&lt;p&gt;Loving these, and the spaced repetition — Mark Goldstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="//michaelnthiessen.com/newsletter"&gt;Sign up here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔥 Vue Tips #25: Reduce, reuse, recursion?</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Thu, 09 Sep 2021 12:24:40 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/vue-tips-25-reduce-reuse-recursion-16dn</link>
      <guid>https://dev.to/michaelthiessen/vue-tips-25-reduce-reuse-recursion-16dn</guid>
      <description>&lt;p&gt;&lt;em&gt;This newsletter was sent out to my list on September 8, 2021. &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; to get emails like this each week!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hey there,&lt;/p&gt;

&lt;p&gt;Today we're talking reduce, dependency injection, React (don't worry, this is still a Vue newsletter), code comments, and conferences.&lt;/p&gt;

&lt;p&gt;But you don't have to take my word for it.&lt;/p&gt;

&lt;p&gt;And just to keep you in the loop: right now there's a &lt;a href="https://michaelnthiessen.com/clean-components" rel="noopener noreferrer"&gt;35% off sale happening for Clean Components&lt;/a&gt;. It ends September 13 at midnight (EDT).&lt;/p&gt;

&lt;p&gt;— Michael&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Simpler testing with dependency injection
&lt;/h2&gt;

&lt;p&gt;Jest makes it easy to mock or stub out functions, but you can also use dependency injection to make things easy to stub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Returns text to be displayed&lt;/span&gt;
    &lt;span class="na"&gt;someMethod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should work&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getByText&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;someMethod&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Test text/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it's coming from outside of the component, it's pretty straightforward to stub it out or mock it however you need, in order to get the test to do what you want.&lt;/p&gt;

&lt;p&gt;You can do this in a variety of ways, depending on your use case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;props&lt;/li&gt;
&lt;li&gt;provide/inject&lt;/li&gt;
&lt;li&gt;Vuex&lt;/li&gt;
&lt;li&gt;custom plugin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(There are probably many more)&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Reducing Objects
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;reduce&lt;/code&gt; function is really great for converting arrays into objects, but it can be intimidating.&lt;/p&gt;

&lt;p&gt;If we have a bunch of items that all have an &lt;code&gt;id&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can reorganize the array into an object, where the key for each item is the item's &lt;code&gt;id&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Grab the id from the item&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;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Add the item to our object&lt;/span&gt;
  &lt;span class="nx"&gt;prev&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Return the object so we can add more items&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prev&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;You get an object that looks 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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to group all objects in an array by a specific property, you can do something very similar:&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;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Grab the property from the item that we want to group by&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;prop&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Add a new array to the object if this is the first one&lt;/span&gt;
  &lt;span class="c1"&gt;// with this value&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Add our item to this array&lt;/span&gt;
  &lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Return the object so we can add more items&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prev&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;Our final object looks 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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prop2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔗 (Sponsored) Keep on top of new tech with DevTrends.io
&lt;/h2&gt;

&lt;p&gt;It seems that every week there's a new JS framework, or a new and better way to write CSS (which is just the old way again).&lt;/p&gt;

&lt;p&gt;Just as you get comfortable writing unit tests you learn that integration tests are actually the way to go. Oh, and the way you've been writing your tests is completely wrong.&lt;/p&gt;

&lt;p&gt;Ugh 🤦‍♂️&lt;/p&gt;

&lt;p&gt;It would be so much simpler if we could ignore everything, but hidden among all these new tools are amazing gems that can transform the way we work.&lt;/p&gt;

&lt;p&gt;But keeping up with all of them is impossible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's why my long time friend, Anthony Gore (who also created Vue.js Developers), created DevTrends.io&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;He does all of the research on new tech and tools for you, and then teaches you the most important details in short, informative videos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://devtrends.io/" rel="noopener noreferrer"&gt;Click here to check out some recent videos&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 Vuex — but for React
&lt;/h2&gt;

&lt;p&gt;This is an interesting short read on writing a Vuex clone, but in React.&lt;/p&gt;

&lt;p&gt;I've taken lots of ideas from React and used them in Vue over the years, but haven't seen many people take ideas from the Vue ecosystem yet.&lt;/p&gt;

&lt;p&gt;What patterns or ideas can you borrow from other frameworks or languages you've used in the past?&lt;/p&gt;

&lt;p&gt;Read it here: &lt;a href="https://itnext.io/i-wrote-vuex-but-for-react-the-challenges-i-faced-and-where-you-can-get-it-d465985d8a5" rel="noopener noreferrer"&gt;I wrote Vuex — but for React!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗞 News: It's conference season!
&lt;/h2&gt;

&lt;p&gt;Yes, I'm just copying and pasting this section each week.&lt;/p&gt;

&lt;p&gt;But you know what? I don't want you to forget about a great conference — like Nuxt Nation, which is happening &lt;em&gt;next week&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We have &lt;em&gt;four&lt;/em&gt; incredible conferences coming up in the next 2 months, all accessible online and two offering (limited) in-person experiences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nuxtnation.com/" rel="noopener noreferrer"&gt;Nuxt Nation&lt;/a&gt; — September 15th — free and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuejs.amsterdam/" rel="noopener noreferrer"&gt;Vuejs Global (Amsterdam)&lt;/a&gt; — October 1st and 4th — Amsterdam and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.london/" rel="noopener noreferrer"&gt;Vue.js Conference (London)&lt;/a&gt; — October 20-21 — London and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuetoronto.com/" rel="noopener noreferrer"&gt;VueConf Toronto&lt;/a&gt; — November 22-23 — free + online&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💬 Comments
&lt;/h2&gt;

&lt;p&gt;"Good code is its own best documentation. As you're about to add a comment, ask yourself, 'How can I improve the code so that this comment isn't needed?'" — Steve McConnell&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Spaced-repetition: Define multiple components in a single file
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every now and then you just need a small component, one that's not worth an entirely new file:&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;// A small, secondary component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SmallComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create a component like you normally would&lt;/span&gt;
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;computedProps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// Use the template property instead of a template block&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;div&amp;gt;Hello!&amp;lt;/div&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Your main component&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SmallComponent&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&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 is perfect for reusing code within a component, where a &lt;code&gt;v-for&lt;/code&gt; doesn't work.&lt;/p&gt;

&lt;p&gt;However, if the code is more complex or is likely to be used by other components, making a proper &lt;a href="https://michaelnthiessen.com/reusable-components" rel="noopener noreferrer"&gt;reusable component&lt;/a&gt; is the best way to go.&lt;/p&gt;

&lt;p&gt;Note: You can get proper syntax highlighting of the HTML string using &lt;a href="https://marketplace.visualstudio.com/items?itemName=Tobermory.es6-string-html" rel="noopener noreferrer"&gt;this VSCode extension&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exclusive tips and insights every week
&lt;/h2&gt;

&lt;p&gt;Join 8135 other Vue devs and &lt;a href="//michaelnthiessen.com/newsletter"&gt;get exclusive tips and insights&lt;/a&gt; like these delivered straight to your inbox, every week.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have great content in your emails. I seriously learn something from every one of them. — Titus Decali&lt;/p&gt;

&lt;p&gt;Thanks for another beautiful tip 🙏 — Victor Onuoha&lt;/p&gt;

&lt;p&gt;Loving these, and the spaced repetition — Mark Goldstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="//michaelnthiessen.com/newsletter"&gt;Sign up here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔥 Vue Tips #24: Mastering Computed Props</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Thu, 02 Sep 2021 12:16:55 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/vue-tips-24-mastering-computed-props-2784</link>
      <guid>https://dev.to/michaelthiessen/vue-tips-24-mastering-computed-props-2784</guid>
      <description>&lt;p&gt;&lt;em&gt;This newsletter was sent out to my list on September 1, 2021. &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; to get emails like this each week!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;They say, "the more the merrier", and I like to be merry*, so here are some more tips.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;* I'm sure you enjoy merriment as well.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;* Also, not the hobbit.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;— Michael&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Master computed props
&lt;/h2&gt;

&lt;p&gt;When a function does more than just return a value, it makes your code more complicated.&lt;/p&gt;

&lt;p&gt;These are called &lt;a href="https://michaelnthiessen.com/side-effect-surgery" rel="noopener noreferrer"&gt;side effects&lt;/a&gt;, and you should never have them inside of a computed prop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchUserInformation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Side effect&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="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;However, fixing this is quite straightforward. We can just move that side effect into a watcher that is triggered whenever the computed prop updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fullName&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchUserInformation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// Side effect&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This applies equally to the composition API, although the syntax is slightly different.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At first glance, this may seem like we made the code more complicated. But actually, we've made it a &lt;a href="https://michaelnthiessen.com/side-effect-surgery" rel="noopener noreferrer"&gt;lot simpler&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This concept is expanded on in my course, &lt;a href="https://michaelnthiessen.com/clean-components" rel="noopener noreferrer"&gt;Clean Components&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 The picture element
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element lets us provide many image options for the browser, which will then decide what the best choice is:&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;picture&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- You can have as many source tags as you want --&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- (or none at all!) --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"big-image.png"&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 1024px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"bigger-image.png"&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 1440px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"biggest-image.png"&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 2048px)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- One img tag is required to actually display the image --&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- and is used as the default choice --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"regular-image.png"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can provide different options based on screen size, resolution, and supported image formats.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture" rel="noopener noreferrer"&gt;mdn docs&lt;/a&gt; have a lot more info on this element.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 (Sponsored) Keep on top of new tech with DevTrends.io
&lt;/h2&gt;

&lt;p&gt;It seems that every week there's a new JS framework, or a new and better way to write CSS (which is just the old way again).&lt;/p&gt;

&lt;p&gt;Just as you get comfortable writing unit tests you learn that integration tests are actually the way to go. Oh, and the way you've been writing your tests is completely wrong.&lt;/p&gt;

&lt;p&gt;Ugh 🤦‍♂️&lt;/p&gt;

&lt;p&gt;It would be so much simpler if we could ignore everything, but hidden among all these new tools are amazing gems that can transform the way we work.&lt;/p&gt;

&lt;p&gt;But keeping up with all of them is impossible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's why my long time friend, Anthony Gore (who also created Vue.js Developers), created DevTrends.io&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;He does all of the research on new tech and tools for you, and then teaches you the most important details in short, informative videos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://devtrends.io/" rel="noopener noreferrer"&gt;Click here to check out some recent videos&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 Using Composables Well
&lt;/h2&gt;

&lt;p&gt;React has hooks, Vue has composables. It's a term you maybe haven't heard before, but &lt;em&gt;composables&lt;/em&gt; are the functions built using the composition API.&lt;/p&gt;

&lt;p&gt;It's not an "official" term, but most of the community has settled on using this term. This is how open source works, right?&lt;/p&gt;

&lt;p&gt;In this article, Markus goes through some common patterns for building composables with the composition API.&lt;/p&gt;

&lt;p&gt;Read it here: &lt;a href="https://markus.oberlehner.net/blog/vue-composition-api-composables/" rel="noopener noreferrer"&gt;Vue Composition API: Composables&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗞 News: 2 weeks until Nuxt Nation
&lt;/h2&gt;

&lt;p&gt;We have &lt;em&gt;four&lt;/em&gt; incredible conferences coming up in the next 3 months, all accessible online and two offering (limited) in-person experiences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nuxtnation.com/" rel="noopener noreferrer"&gt;Nuxt Nation&lt;/a&gt; — September 15th — free and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuejs.amsterdam/" rel="noopener noreferrer"&gt;Vuejs Global (Amsterdam)&lt;/a&gt; — October 1st and 4th — Amsterdam and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.london/" rel="noopener noreferrer"&gt;Vue.js Conference (London)&lt;/a&gt; — October 20-21 — London and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuetoronto.com/" rel="noopener noreferrer"&gt;VueConf Toronto&lt;/a&gt; — November 22-23 — free + online&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💬 90%
&lt;/h2&gt;

&lt;p&gt;"The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time." — Tom Cargill&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Spaced-repetition: Shorthand for named slots
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Named slots also have a shorthand syntax, one that's much nicer to look at.&lt;/p&gt;

&lt;p&gt;Instead of writing 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;DataTable&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;v-slot:header&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;TableHeader&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/DataTable&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can write 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;DataTable&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#header&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;TableHeader&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/DataTable&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not a huge difference, but a little cleaner for sure. I think the &lt;code&gt;#&lt;/code&gt; character is easier to pick out than &lt;code&gt;v-slot&lt;/code&gt; when reading code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exclusive tips and insights every week
&lt;/h2&gt;

&lt;p&gt;Join 8135 other Vue devs and &lt;a href="//michaelnthiessen.com/newsletter"&gt;get exclusive tips and insights&lt;/a&gt; like these delivered straight to your inbox, every week.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have great content in your emails. I seriously learn something from every one of them. — Titus Decali&lt;/p&gt;

&lt;p&gt;Thanks for another beautiful tip 🙏 — Victor Onuoha&lt;/p&gt;

&lt;p&gt;Loving these, and the spaced repetition — Mark Goldstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="//michaelnthiessen.com/newsletter"&gt;Sign up here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔥 Vue Tips #23: Why there must be one source of truth</title>
      <dc:creator>Michael Thiessen</dc:creator>
      <pubDate>Tue, 31 Aug 2021 12:16:59 +0000</pubDate>
      <link>https://dev.to/michaelthiessen/vue-tips-23-why-there-must-be-one-source-of-truth-58hi</link>
      <guid>https://dev.to/michaelthiessen/vue-tips-23-why-there-must-be-one-source-of-truth-58hi</guid>
      <description>&lt;p&gt;&lt;em&gt;This newsletter was sent out to my list on August 25, 2021. &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; to get emails like this each week!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Heyo,&lt;/p&gt;

&lt;p&gt;I've got some more tips, an article, and a quote — as always.&lt;/p&gt;

&lt;p&gt;If you know someone who would enjoy these tips, forward this email to them or send them &lt;a href="https://michaelnthiessen.com/newsletter" rel="noopener noreferrer"&gt;here&lt;/a&gt; so they can sign themselves up.&lt;/p&gt;

&lt;p&gt;The more people that sign up, the more I feel obligated to pack in tons of value, and that's especially good for you, right?&lt;/p&gt;

&lt;p&gt;So share this newsletter with others, even if it's just for purely selfish reasons 😏&lt;/p&gt;

&lt;p&gt;— Michael&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Why there must be one source of truth
&lt;/h2&gt;

&lt;p&gt;This is the most important principle of state management that I know:&lt;/p&gt;

&lt;p&gt;Each piece of state has a single owner, a single source of truth.&lt;/p&gt;

&lt;p&gt;No one else is allowed to modify the state. It's just borrowed temporarily.&lt;/p&gt;

&lt;p&gt;If you have an array in a Vuex store, only that Vuex store can update it. Anywhere in your app that needs that value &lt;em&gt;must&lt;/em&gt; get it from the store (whether directly or through another component).&lt;/p&gt;

&lt;p&gt;If the state is owned by a component, only that component can modify it. This means other comopnents must emit an event to that component, which can then decide what it wants to do.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;If you allow state to be modified from anywhere, your code becomes a tangled mess.&lt;/p&gt;

&lt;p&gt;With a single source of truth, you can easily understand what's happening.&lt;/p&gt;

&lt;p&gt;The best code is easily understood.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 Aria roles you didn't know you needed
&lt;/h2&gt;

&lt;p&gt;Aria roles are used to tell a screenreader what an element is for.&lt;/p&gt;

&lt;p&gt;This is really important when the native HTML elemen just doesn't exist (eg. roles like &lt;code&gt;toolbar&lt;/code&gt; and &lt;code&gt;alert&lt;/code&gt;) or when you're using a different HTML element for design or technical reasons (eg. wrapping a &lt;code&gt;radio&lt;/code&gt; button to style it).&lt;/p&gt;

&lt;p&gt;But please, remember that you should always use the semantic element where you can. This is always the best and most effective solution.&lt;/p&gt;

&lt;p&gt;There are six different categories of aria roles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Widget - roles like &lt;code&gt;button&lt;/code&gt;, &lt;code&gt;checkbox&lt;/code&gt;, &lt;code&gt;separator&lt;/code&gt;, &lt;code&gt;tab&lt;/code&gt;, or &lt;code&gt;scrollbar&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Composite - roles like &lt;code&gt;combobox&lt;/code&gt; and &lt;code&gt;listbox&lt;/code&gt; (these are for dropdown menus), &lt;code&gt;radiogroup&lt;/code&gt;, or &lt;code&gt;tree&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Document structure - this includes &lt;code&gt;article&lt;/code&gt;, &lt;code&gt;presentation&lt;/code&gt;, &lt;code&gt;figure&lt;/code&gt;, &lt;code&gt;feed&lt;/code&gt;, and &lt;code&gt;directory&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Landmark - &lt;code&gt;banner&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;navigation&lt;/code&gt;, and &lt;code&gt;region&lt;/code&gt; are roles in this category&lt;/li&gt;
&lt;li&gt;Live region - &lt;code&gt;alert&lt;/code&gt;, &lt;code&gt;log&lt;/code&gt;, &lt;code&gt;marquee&lt;/code&gt;, and &lt;code&gt;status&lt;/code&gt; are roles that might update with real-time information&lt;/li&gt;
&lt;li&gt;Window - &lt;code&gt;alertdialog&lt;/code&gt; and &lt;code&gt;dialog&lt;/code&gt; are the only two roles in this category&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can check out the full list here: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#roles" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#roles&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 (Sponsored) HarperDB, the best db for frontend devs
&lt;/h2&gt;

&lt;p&gt;...but it's not &lt;em&gt;exactly&lt;/em&gt; a database.&lt;/p&gt;

&lt;p&gt;For me, the most frustrating part of building an app is all of the backend stuff.&lt;/p&gt;

&lt;p&gt;You need to find somewhere to persist the data, another place to put the API, and then spend hours configuring and setting it all up. If you pick the one that's easy to use, your project will outgrow it. But if you go all-in with AWS you never even get the project off the ground 🤦‍♂️.&lt;/p&gt;

&lt;p&gt;HarperDB does all of this stuff for you, in an easy-to-use package that grows with your project. Here are its best features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NoSQL and SQL hybrid&lt;/li&gt;
&lt;li&gt;Custom API functions (powered by Fastify)&lt;/li&gt;
&lt;li&gt;Simple REST API to access everything&lt;/li&gt;
&lt;li&gt;Really easy to use admin dashboard to create tables, add or delete data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've only played around with HarperDB a bit, but so far I'm impressed, and I plan to use it on my next project.&lt;/p&gt;

&lt;p&gt;The best way to get started is &lt;a href="https://harperdb.io/docs/getting-started/" rel="noopener noreferrer"&gt;through the HarperDB docs&lt;/a&gt;, but they also have a &lt;a href="https://api.harperdb.io/" rel="noopener noreferrer"&gt;well-documented API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There's also this &lt;a href="https://github.com/cassidoo/book-rating-demo" rel="noopener noreferrer"&gt;demo in React&lt;/a&gt;. There's nothing yet for Vue + HarperDB, but that just means you could be the one to build it!&lt;/p&gt;

&lt;h2&gt;
  
  
  📜 The Dark Side of Nuxt
&lt;/h2&gt;

&lt;p&gt;Nuxt is a fantastic framework, but even the best frameworks aren't perfect.&lt;/p&gt;

&lt;p&gt;It this article, Jonas uses his experience as a consultant to explore the dark side of Nuxt, and how to refactor the Nuxt Hacker News clone to use Fastify and Vite to eliminate some of those dark spots.&lt;/p&gt;

&lt;p&gt;Read it here: &lt;a href="https://vuejsdevelopers.com/2021/03/23/nuxt-vite-fastify/" rel="noopener noreferrer"&gt;Rewriting Nuxt HN with Fastify, Vite and Vue 3&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗞 News: It's (still) conference season!
&lt;/h2&gt;

&lt;p&gt;If you didn't get the memo last week, we have &lt;em&gt;four&lt;/em&gt; incredible conferences coming up in the next 3 months, all accessible online and two offering (limited) in-person experiences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nuxtnation.com/" rel="noopener noreferrer"&gt;Nuxt Nation&lt;/a&gt; — September 15th — free and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuejs.amsterdam/" rel="noopener noreferrer"&gt;Vuejs Global (Amsterdam)&lt;/a&gt; — October 1st and 4th — Amsterdam and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.london/" rel="noopener noreferrer"&gt;Vue.js Conference (London)&lt;/a&gt; — October 20-21 — London and online&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.vuetoronto.com/" rel="noopener noreferrer"&gt;VueConf Toronto&lt;/a&gt; — November 22-23 — free + online&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💬 Simplicity
&lt;/h2&gt;

&lt;p&gt;"Complicated code is a sign that you don't understand your program well enough to make it simple." — Steve McConnell&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Spaced-repetition: Clean up your Tailwind classes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After using Tailwind for awhile you'll start to notice you end up with a lot of elements that have tons of classes on them:&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mx-5 w-1/2 md:mx-0 md:w-auto mb-8 flex justify-end"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can combine all of these utility classes together into a single class by using the &lt;code&gt;@apply&lt;/code&gt; directive:&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;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"combined"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"combined"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.combined&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;mx-5&lt;/span&gt; &lt;span class="err"&gt;w-1/2&lt;/span&gt; &lt;span class="py"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;mx-0&lt;/span&gt; &lt;span class="n"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;w-auto&lt;/span&gt; &lt;span class="n"&gt;mb-8&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt; &lt;span class="n"&gt;justify-end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you reuse those styles without having to create a whole new Vue component for them.&lt;/p&gt;

&lt;p&gt;Of course, one of the best parts of Vue is that we can create reusable components, but not everything needs to be (or deserves to be) it's own component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exclusive tips and insights every week
&lt;/h2&gt;

&lt;p&gt;Join 8135 other Vue devs and &lt;a href="//michaelnthiessen.com/newsletter"&gt;get exclusive tips and insights&lt;/a&gt; like these delivered straight to your inbox, every week.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have great content in your emails. I seriously learn something from every one of them. — Titus Decali&lt;/p&gt;

&lt;p&gt;Thanks for another beautiful tip 🙏 — Victor Onuoha&lt;/p&gt;

&lt;p&gt;Loving these, and the spaced repetition — Mark Goldstein&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="//michaelnthiessen.com/newsletter"&gt;Sign up here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
