<?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: Obiwan Pelosi</title>
    <description>The latest articles on DEV Community by Obiwan Pelosi (@obiwanpelosi).</description>
    <link>https://dev.to/obiwanpelosi</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%2F432730%2F4a4fef21-bc9b-42b5-aa38-4786f3f99c7a.jpeg</url>
      <title>DEV Community: Obiwan Pelosi</title>
      <link>https://dev.to/obiwanpelosi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/obiwanpelosi"/>
    <language>en</language>
    <item>
      <title>The Future of Web UI: Trends in React, Vue &amp; Svelte</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Fri, 24 Oct 2025 09:22:45 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/the-future-of-web-ui-trends-in-react-vue-svelte-7l8</link>
      <guid>https://dev.to/obiwanpelosi/the-future-of-web-ui-trends-in-react-vue-svelte-7l8</guid>
      <description>&lt;p&gt;&lt;strong&gt;"React was a mistake"&lt;/strong&gt; -- Twitter User&lt;/p&gt;

&lt;p&gt;On September 12, Cloudflare experienced a dashboard and API outage that lasted for over an hour. It was later discovered that cloudflare DDoSed itself; the culprit ? a useEffect bug that lead to repeated API calls. &lt;/p&gt;

&lt;p&gt;This incident reignited the never-ending debate about the superior frontend framework and if you've spent anytime online, it really is never-ending. &lt;/p&gt;

&lt;p&gt;If you opened this article to find out the "&lt;em&gt;winner&lt;/em&gt;", that's too damn bad. It doesn't really matter anyway, my two cents ? Pick what feels right for you or your team, your constraints, and the problem at hand.&lt;/p&gt;

&lt;p&gt;In this article, what we want to do instead is to dig into the data. We’ll explore how React, Vue and Svelte stack up in terms of adoption, satisfaction and trend-momentum. From those numbers you can draw your own conclusions about the future of web UI.&lt;/p&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  How We’re Looking at the Data
&lt;/h2&gt;

&lt;p&gt;The goal here isn’t to crown a new “&lt;em&gt;king of JavaScript frameworks&lt;/em&gt;,” but to understand where the front-end ecosystem is heading, using &lt;strong&gt;real data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Most of the numbers and trends in this article come directly from the latest &lt;strong&gt;&lt;a href="https://2024.stateofjs.com/en-US/libraries/front-end-frameworks/" rel="noopener noreferrer"&gt;State of JavaScript Survey&lt;/a&gt;&lt;/strong&gt;, specifically the Front-end Frameworks section. It’s one of the most comprehensive developer sentiment and usage surveys out there, covering thousands of responses from developers worldwide.&lt;/p&gt;

&lt;p&gt;Here’s how we’re approaching it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Metrics we’re focusing on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Usage&lt;/strong&gt;: how many developers actually use the framework, especially in production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retention&lt;/strong&gt;: how many would use it again which is a good measure of satisfaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Happiness&lt;/strong&gt;: the overall sentiment developers have toward each tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trends over time&lt;/strong&gt;: how these frameworks have grown, stabilized, or declined across survey years.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our lens:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’re keeping it objective; numbers first, opinions later. But we’ll still interpret what those numbers could mean for the future of UI development.&lt;/p&gt;

&lt;p&gt;Of course, it’s worth noting that surveys like this aren’t a perfect reflection of the entire industry (after all, not every developer fills them out). But they do give a pretty reliable pulse on where the developer community’s excitement and frustrations lie.&lt;/p&gt;

&lt;p&gt;Now that we know what we’re measuring and why, let’s see what the numbers actually say.&lt;/p&gt;

&lt;h2&gt;
  
  
  Popularity &amp;amp; Adoption: The Framework League Table
&lt;/h2&gt;

&lt;p&gt;Let’s start with the question that sparks most arguments at meetups and online threads: which framework is the most popular?&lt;/p&gt;

&lt;p&gt;Unsurprisingly, &lt;strong&gt;React&lt;/strong&gt; still wears the crown. According to the State of JS 2024 Survey, React remains the most widely used front-end framework, with roughly &lt;strong&gt;eight out of ten&lt;/strong&gt; respondents saying they’ve worked with it in some capacity; and more than &lt;strong&gt;8,500&lt;/strong&gt; developers using it at work. That’s a huge footprint.&lt;/p&gt;

&lt;p&gt;Coming in second is &lt;strong&gt;Vue.js&lt;/strong&gt;, holding its ground as a mature and widely trusted alternative. About &lt;strong&gt;4,000&lt;/strong&gt; respondents reported using Vue professionally, which translates to &lt;strong&gt;just over half of all&lt;/strong&gt; developers surveyed. Vue’s adoption has plateaued a bit compared to its explosive early growth years, but it’s clearly not going anywhere; it’s found its niche and holds onto it well.&lt;/p&gt;

&lt;p&gt;And then there’s Svelte, the minimalist rising star. While only 1,400 developers in the survey said they use it at work (around a quarter of respondents), Svelte has something the others don’t: a cult-like loyalty and satisfaction score that punches way above its weight.&lt;/p&gt;

&lt;p&gt;Here’s how they line up if we strip away all the noise and look purely at adoption numbers:&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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg4556s48lvqffucp8epz.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg4556s48lvqffucp8epz.png" alt="Adoption numbers of frontend frameworks" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So yes — &lt;strong&gt;React&lt;/strong&gt; continues to dominate by sheer numbers, but &lt;strong&gt;Vue&lt;/strong&gt; and &lt;strong&gt;Svelte&lt;/strong&gt; aren’t just background noise. Vue has solidified itself as the dependable second choice, while Svelte has captured the hearts (and code editors) of developers looking for something refreshingly different.&lt;/p&gt;

&lt;p&gt;Popularity, though, only tells part of the story. What really matters is how much people actually enjoy using these tools; and whether they’d choose them again.&lt;br&gt;
That’s where things start to get interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retention &amp;amp; Satisfaction: Love It or Leave It?
&lt;/h2&gt;

&lt;p&gt;Popularity is great, but let’s be honest; just because everyone’s using something doesn’t mean they’re happy about it. Just ask a cloudflare developer 😉.&lt;/p&gt;

&lt;p&gt;That’s why it’s worth looking at a more telling metric: &lt;strong&gt;retention&lt;/strong&gt;; how many developers would willingly use a framework again. It’s a solid indicator of developer satisfaction and long-term staying power.&lt;/p&gt;

&lt;p&gt;Here’s what the State of JS 2024 Survey tells us:&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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxm2ot9hnoo3qae43qee.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffxm2ot9hnoo3qae43qee.png" alt="Retention rate of frontend frameworks" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, while &lt;strong&gt;React&lt;/strong&gt; continues to lead in raw usage, &lt;strong&gt;Vue&lt;/strong&gt; and &lt;strong&gt;Svelte&lt;/strong&gt; take the crown when it comes to developer joy.&lt;/p&gt;

&lt;p&gt;In other words, most React users stick around mostly because it’s the industry default. Vue and Svelte users, on the other hand, stay because they want to.&lt;/p&gt;

&lt;p&gt;And this sentiment shows in the happiness charts too. The survey’s “Front-end Frameworks Happiness” graph paints a clear picture: React’s curve is starting to flatten, Vue’s stays consistently high, and Svelte’s line shoots to the top.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The takeaway?&lt;/strong&gt;&lt;br&gt;
If the front-end world were a dating app, React would be the long-term partner you’ve settled down with. Vue would be the balanced, reliable choice you actually enjoy spending time with. And Svelte — well, that’s the exciting new fling everyone’s talking about.&lt;/p&gt;

&lt;p&gt;But beyond love and loyalty, the real question is: where are these frameworks headed next? Let’s zoom out and see how their stories have evolved over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage Trends Over Time: The Shifting Front-End Landscape
&lt;/h2&gt;

&lt;p&gt;Frameworks, like fashion trends, have their moments. &lt;strong&gt;React&lt;/strong&gt; had its meteoric rise in the late 2010s, &lt;strong&gt;Vue&lt;/strong&gt; exploded shortly after, and Svelte quietly entered the chat. &lt;/p&gt;

&lt;p&gt;If you glance at the survey’s “&lt;em&gt;Ratios Over Time&lt;/em&gt;” chart, you’ll notice a few clear storylines:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React&lt;/strong&gt; is no longer the scrappy newcomer; it’s the default. Its usage curve peaked and then began to level off. That’s not necessarily decline; it’s maturity. React has saturated the ecosystem so thoroughly that growth can only be incremental now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vue&lt;/strong&gt; remains the solid number-two choice. After its explosive early years, it has settled into a steady rhythm. The data shows Vue holding its ground, even gaining a few points in retention, suggesting that those who adopt it tend to stick.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Svelte&lt;/strong&gt;, meanwhile, is on a gentle but consistent upward trajectory. It doesn’t have the mass adoption of React or Vue (yet), but its curve is pointing in exactly the right direction; growing steadily year after year.&lt;/p&gt;

&lt;p&gt;The survey summary even puts it succinctly:&lt;/p&gt;

&lt;p&gt;_“Vue managed to keep its number two spot — as well as gained a whopping three spots in terms of retention percentage! Meanwhile, Svelte usage is increasing at a steady pace, while it continues to top the rankings in terms of overall positive opinions.”&lt;br&gt;
_&lt;/p&gt;

&lt;p&gt;In simpler terms: React’s dominant, Vue’s stable, and Svelte’s on the rise.&lt;/p&gt;

&lt;p&gt;So where does that leave us?&lt;br&gt;
It paints a front-end ecosystem that’s diversifying rather than consolidating. Instead of one framework crushing all others, we’re seeing multiple strong players thriving in their own lanes — and that’s actually great news. It means developers have options that fit different project needs and preferences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What This Means for the Future of Web UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If there’s one thing the State of JS 2024 data makes clear, it’s that the front-end landscape isn’t about one framework winning anymore — it’s about evolution and coexistence.&lt;/p&gt;

&lt;p&gt;React has solidified its role as the dependable heavyweight — the foundation of countless production apps and entire ecosystems. Vue continues to thrive as the pragmatic alternative, offering a gentle learning curve without sacrificing power and with its latest approach to reactivity system, it's now believed to be the fastest of them all. And Svelte? It’s quietly shaping the future, reminding everyone that innovation often starts at the fringes.&lt;/p&gt;

&lt;p&gt;We’re entering a phase where the “React vs. Vue” debate feels outdated. Each framework now appeals to a different kind of developer mindset&lt;/p&gt;

&lt;p&gt;The future of Web UI isn’t about choosing sides; it’s about choosing fit. As new tools like Solid, Qwik, and Signals-based reactivity models gain traction, one truth remains: the front-end world never stands still.&lt;/p&gt;

&lt;p&gt;So whether you’re a React loyalist, a Vue enthusiast, or a Svelte experimenter, the key is to stay curious, adaptable, and willing to unlearn. Because in this space, today’s underdog might just be tomorrow’s default.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>🎉 Vue-icons (a react-icons equivalent) is finally here, LFG</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Sun, 29 Jun 2025 08:20:26 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/vue-icons-a-react-icons-equivalent-is-finally-here-lfg-1032</link>
      <guid>https://dev.to/obiwanpelosi/vue-icons-a-react-icons-equivalent-is-finally-here-lfg-1032</guid>
      <description>&lt;p&gt;If you've ever used React, you've probably come across the excellent &lt;a href="https://react-icons.github.io/react-icons" rel="noopener noreferrer"&gt;react-icons&lt;/a&gt; library — a single, tree-shakeable, well-typed icon package that just works.&lt;/p&gt;

&lt;p&gt;But for Vue developers? The icon ecosystem has felt scattered and inconsistent... until now.&lt;/p&gt;

&lt;p&gt;👉 Say hello to Vue Icons Library — a modern, TypeScript-first icon library designed specifically for Vue.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Quick Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🧑‍💻 Visit the Website&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📦 GitHub Repository&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🚀 Install Now:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;npm install vue-icons-lib&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 What is Vue Icons Library?
&lt;/h2&gt;

&lt;p&gt;Vue Icons Library is the Vue 3 equivalent of react-icons — a comprehensive, zero-dependency, tree-shakeable icon library that bundles 7+ popular icon sets into a single, intuitive API.&lt;/p&gt;

&lt;p&gt;Built with modern Vue tooling, it brings performance, type safety, and simplicity to working with icons in your Vue apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;✅ Tree-shakeable by design – Only the icons you import are included in your bundle&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;💡 TypeScript-first – Full type definitions with IDE IntelliSense&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧩 Built for Vue 3 – Composition API, script setup support, and reactivity-ready&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚡ Lightweight &amp;amp; Fast – Clean SVGs, optimized build pipeline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧱 Consistent API – Unified props (size, color, class, etc.) across all icons&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;♿ Accessible – Proper viewBox and accessible by default&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🌐 SSR Compatible – Works great with Nuxt, Vite SSR, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎨 Included Icon Sets
&lt;/h2&gt;

&lt;p&gt;Vue Icons Library ships with thousands of icons from your favorite sets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ant Design Icons&lt;/li&gt;
&lt;li&gt;Box Icons&lt;/li&gt;
&lt;li&gt;Circum Icons&lt;/li&gt;
&lt;li&gt;CSS.gg Icons&lt;/li&gt;
&lt;li&gt;Dev Icons&lt;/li&gt;
&lt;li&gt;Feather Icons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More sets (like Material Icons and Heroicons) are coming soon!&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Getting Started
&lt;/h2&gt;

&lt;p&gt;Installation:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install vue-icons-lib&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Basic usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { FiHeart } from 'vue-icons-lib/fi';
import { AiFillStar } from 'vue-icons-lib/ai';
import { BxHome } from 'vue-icons-lib/bx';
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;FiHeart color="#ff6b6b" size="24px" /&amp;gt;
    &amp;lt;AiFillStar color="#ffd700" /&amp;gt;
    &amp;lt;BxHome class="home-icon" /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Advanced Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { FiHeart } from "vue-icons-lib/fi";

function handleClick() {
  console.log("Heart clicked!");
}
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;FiHeart
    size="32px"
    color="#ff6b6b"
    class="heart-icon"
    style="cursor: pointer; transition: transform 0.2s;"
    @click="handleClick"
  /&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🚀 Real-World Usage Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { FiHeart, FiStar, FiShare, FiBookmark } from "vue-icons-lib/fi";

const props = defineProps&amp;lt;{
  isLiked: boolean;
  isStarred: boolean;
}&amp;gt;();
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;div class="action-buttons"&amp;gt;
    &amp;lt;FiHeart
      :color="isLiked ? '#ff6b6b' : '#666'"
      size="20px"
      class="action-icon"
      @click="$emit('toggle-like')"
    /&amp;gt;
    &amp;lt;FiStar
      :color="isStarred ? '#ffd700' : '#666'"
      size="20px"
      class="action-icon"
      @click="$emit('toggle-star')"
    /&amp;gt;
    &amp;lt;FiShare size="20px" class="action-icon" @click="$emit('share')" /&amp;gt;
    &amp;lt;FiBookmark size="20px" class="action-icon" @click="$emit('bookmark')" /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📦 Bundle Optimization&lt;/p&gt;

&lt;p&gt;Before (bad):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import * as Icons from 'some-icon-library'; // 😱 All icons are bundled
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After (with Vue Icons Library):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { FiHeart, FiStar } from 'vue-icons-lib/fi'; // ✅ Only what you need
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result? ⚡ Smaller bundle size and faster load times — especially important for production apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Compatibility &amp;amp; Support
&lt;/h2&gt;

&lt;p&gt;✅ Vue 2 &amp;amp; 3.x&lt;/p&gt;

&lt;p&gt;✅ Vite, Webpack, Rollup&lt;/p&gt;

&lt;p&gt;✅ TypeScript&lt;/p&gt;

&lt;p&gt;✅ SSR (Nuxt.js, etc.)&lt;/p&gt;

&lt;p&gt;✅ Tree-shaking compatible bundlers&lt;/p&gt;

&lt;p&gt;✅ All modern browsers&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝 Get Involved
&lt;/h2&gt;

&lt;p&gt;Vue Icons Library is open source and welcomes contributions!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;💬 Submit issues or feature requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🛠 Add more icon sets or improve performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🧾 Help refine the docs and examples&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🌟 Star the repo if you like the project!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub → &lt;a href="//github.com/obiwanpelosi/vue-icons-package"&gt;github.com/vue-icons-lib&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 Explore the icons and docs site &lt;a href="https://vueicons.netlify.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>🚀 Supercharge Your Web Apps with Web Workers in React and Vue</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Mon, 19 May 2025 15:00:46 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/supercharge-your-web-apps-with-web-workers-in-react-and-vue-34gf</link>
      <guid>https://dev.to/obiwanpelosi/supercharge-your-web-apps-with-web-workers-in-react-and-vue-34gf</guid>
      <description>&lt;p&gt;Have you ever noticed your web app freezing for a moment while processing something complex—maybe parsing a huge JSON file, crunching numbers, or resizing an image? 😬&lt;/p&gt;

&lt;p&gt;That’s your main thread choking under pressure.&lt;/p&gt;

&lt;p&gt;But fear not! There's a superhero in the browser world that can take some of the heavy lifting off your main thread’s shoulders. Meet &lt;strong&gt;Web Workers&lt;/strong&gt;, your friendly background JavaScript buddies.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore how to integrate Web Workers into both React and Vue applications. Let’s make your apps faster, smoother, and more responsive, with some fun along the way!&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Why even use Web Workers?
&lt;/h2&gt;

&lt;p&gt;Javascript is single-threaded which means the browser's main thread is responsible for handling both UI rendering and also logic. This can get "too much" and cause lags especially when performing expensive operations. Web Workers run in a separate thread from the main browser thread. This means they can handle resource-heavy tasks without blocking your UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ When You Should Use Web Workers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🔁 1. Heavy Computation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're performing tasks that take more than a few milliseconds, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Processing large datasets (e.g., CSV parsing, log processing)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Image manipulation (e.g., filters, compression)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cryptographic computations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Complex math or simulations&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tasks block the main UI thread if not offloaded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📈 2. Real-time Data Processing:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you're streaming and processing real-time data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;WebSocket streams (e.g., trading dashboards, multiplayer games)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Audio/video analysis&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IoT sensor data parsing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🔍 3. Machine Learning Inference in the Browser&lt;/strong&gt;&lt;br&gt;
Using models (like TensorFlow.js or ONNX) can strain the main thread. Running inference in a Web Worker can keep the UI smooth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧠 4. Apps Needing Maximum Responsiveness&lt;/strong&gt;&lt;br&gt;
Apps where UI responsiveness is crucial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Graphic editors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code editors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collaborative tools&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🚫 When Not to Use Web Workers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🐣 1. Simple or Short Tasks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don’t use a worker for trivial operations. Spinning up a Web Worker has a cost, especially for very small jobs—it could be slower than just running the task in the main thread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔗 2. If You Need Access to the DOM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Web Workers can’t:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Read/write the DOM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access window, document, or localStorage directly. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use them only for data processing—not UI manipulation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📦 3. If You’re Already Using Backend Processing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If a task is already handled by a backend service or API, using a worker to process it locally might be redundant or even wasteful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔌 4. When Browser Support Is Critical&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Web Workers are widely supported, but there may be edge cases (e.g., very old mobile browsers or embedded webviews) where they're unavailable. Test accordingly.&lt;/p&gt;
&lt;h2&gt;
  
  
  🔨 Web Workers in Action (Vanilla Style)
&lt;/h2&gt;

&lt;p&gt;Before diving into frameworks, let’s get a sense of how Web Workers work.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;worker.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// This runs in a separate thread
self.onmessage = function (event) {
  const data = event.data;
  const result = data * 2; // simulate heavy task
  self.postMessage(result);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;main.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const worker = new Worker('worker.js');

worker.postMessage(10);

worker.onmessage = function (event) {
  console.log('Result from worker:', event.data); // 20
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚛️ Using Web Workers in React
&lt;/h2&gt;

&lt;p&gt;Let’s integrate a worker into a React app with Vite. We'll create a component that uses a worker to perform a CPU-heavy calculation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔧 Setup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, create a worker file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/workers/counterWorker.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;self.onmessage = function (e) {
  const num = e.data;
  let result = 0;
  for (let i = 0; i &amp;lt; num; i++) result += i;
  self.postMessage(result);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;🧩 React Component Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you have a component that has to loop over 10 million items&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HeavyCounter.jsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';

export default function HeavyCounter() {
  const [result, setResult] = useState(null);
  const [loading, setLoading] = useState(false);

  const runWorker = () =&amp;gt; {
    setLoading(true);
    const worker = new Worker(new URL('@/workers/counterWorker.js', import.meta.url), { type:'module' });
    worker.postMessage(1e7); // pass 10 million items to worker


    worker.onmessage = (e) =&amp;gt; {
      setResult(e.data);
      setLoading(false);
      worker.terminate();
    };
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;🔁 Heavy Counter (React + Worker)&amp;lt;/h2&amp;gt;
      &amp;lt;button onClick={runWorker} disabled={loading}&amp;gt;
        {loading ? 'Calculating...' : 'Run Task'}
      &amp;lt;/button&amp;gt;
      {result &amp;amp;&amp;amp; &amp;lt;p&amp;gt;Result: {result}&amp;lt;/p&amp;gt;}
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🧩 Using Web Workers in Vue 3&lt;/p&gt;

&lt;p&gt;Vue makes this just as easy, especially with Vite.&lt;/p&gt;

&lt;p&gt;Using the same worker setup, we can create a vue component that utilizes it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HeavyCounter.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { ref } from 'vue';

const result = ref(null);
const loading = ref(false);

const runWorker = () =&amp;gt; {
  loading.value = true;
      const worker = new Worker(new URL('@/workers/counterWorker.js', import.meta.url), { type:'module' });


  worker.postMessage(1e7);

  worker.onmessage = (e) =&amp;gt; {
    result.value = e.data;
    loading.value = false;
    worker.terminate();
  };
};
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;h2&amp;gt;🔁 Heavy Counter (Vue + Worker)&amp;lt;/h2&amp;gt;
    &amp;lt;button @click="runWorker" :disabled="loading"&amp;gt;
      {{ loading ? 'Calculating...' : 'Run Task' }}
    &amp;lt;/button&amp;gt;
    &amp;lt;p v-if="result !== null"&amp;gt;Result: {{ result }}&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Communication with the worker is asynchronous, you listen for responses from the worker using &lt;code&gt;worker.onmessage&lt;/code&gt; and send data to it using &lt;code&gt;worker.postMessage&lt;/code&gt;. &lt;br&gt;
Always remember to call &lt;code&gt;worker.terminate()&lt;/code&gt; to stop the worker once it's done to free up resources.&lt;/p&gt;

&lt;p&gt;🧰 Bonus: Want more power? Look into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker" rel="noopener noreferrer"&gt;Shared Workers&lt;/a&gt; (for multi-tab communication)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/GoogleChromeLabs/comlink#readme" rel="noopener noreferrer"&gt;Comlink &lt;/a&gt;– abstracts away postMessage/onmessage&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I really hope you found this article helpful, 🚀 Happy threading!&lt;/p&gt;

</description>
      <category>react</category>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>✨ Vue Tip: Add Undo/Redo to Your App with useRefHistory</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Mon, 14 Apr 2025 09:30:00 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/vue-tip-add-undoredo-to-your-app-with-userefhistory-c7a</link>
      <guid>https://dev.to/obiwanpelosi/vue-tip-add-undoredo-to-your-app-with-userefhistory-c7a</guid>
      <description>&lt;p&gt;When building dynamic interfaces, especially where users can make changes (text editors, or design tools), providing undo and redo functionality dramatically improves user experience.&lt;/p&gt;

&lt;p&gt;Thankfully, Vue + VueUse makes this a breeze with the &lt;code&gt;useRefHistory&lt;/code&gt; composable.&lt;/p&gt;

&lt;p&gt;🔄 &lt;strong&gt;What is useRefHistory?&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;useRefHistory&lt;/code&gt; from the &lt;a href="https://vueuse.org/core/useRefHistory/" rel="noopener noreferrer"&gt;@vueuse/core&lt;/a&gt; package allows you to track the history of changes to a ref in Vue. It enables you to programmatically undo or redo changes made to that ref, just like in text editors or drawing apps.&lt;/p&gt;

&lt;p&gt;💡 Let's Build a Simple To-do App with Undo/Redo&lt;/p&gt;

&lt;p&gt;In this example, we have a list of to-do items. Every time you add or remove an item, the change is tracked — and you can go back and forth using Undo and Redo buttons.&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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fia0md02zjz9yuaggjkb7.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fia0md02zjz9yuaggjkb7.png" alt="Project UI" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🧠 The Key Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { ref } from "vue";
import { useRefHistory } from "@vueuse/core";

const todoItems = ref(["walk my dog", "go to the gym", "eat lunch"]);
const add = (e) =&amp;gt; {
  todoItems.push(e.target.value);
  e.target.value = "";
};
const remove = (index) =&amp;gt; todoItems.value.splice(index, 1);

// 👇 Track changes to `todoItems` and enable undo/redo
const { undo, redo } = useRefHistory(todoItems, {
  deep: true,
});
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;button @click="undo"&amp;gt;Undo&amp;lt;/button&amp;gt;
    &amp;lt;button @click="redo"&amp;gt;Redo&amp;lt;/button&amp;gt;

    &amp;lt;input type="text" @keyup.enter="add" placeholder="Add todo" /&amp;gt;
    &amp;lt;ul&amp;gt;
      &amp;lt;li v-for="(item, index) in todoItems" :key="item"&amp;gt;
        {{ item }}
        &amp;lt;button @click="remove(index)"&amp;gt;Remove&amp;lt;/button&amp;gt;
      &amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here it is in action:&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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flduw3i3ozyjzc8sdt7qb.gif" 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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flduw3i3ozyjzc8sdt7qb.gif" alt="image showing ref history in action" width="1280" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🛠 &lt;strong&gt;Use Cases for useRefHistory&lt;/strong&gt;&lt;br&gt;
Here are a few places where useRefHistory can be a game changer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Forms: Revert user inputs step-by-step (e.g., a multi-field form with preview).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design Tools: Let users undo shapes, colors, or movements in a canvas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Text Editors: Implement undo/redo in markdown or WYSIWYG editors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Games: Go back to previous states (e.g., board games like chess).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Collaborative Tools: Temporarily revert shared content locally before syncing changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📝 &lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;useRefHistory&lt;/code&gt; is a simple yet powerful utility that adds professional polish to your Vue apps. Whether you're building productivity tools or just want to offer a better user experience, this is definitely one to have in your toolbox.&lt;/p&gt;

&lt;p&gt;Want to see the full code? Try it yourself &lt;a href="https://codesandbox.io/p/devbox/n44d8j" rel="noopener noreferrer"&gt;here&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>frontend</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I love slots, do you ?</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Wed, 12 Mar 2025 12:19:16 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/i-love-slots-do-you--4h5d</link>
      <guid>https://dev.to/obiwanpelosi/i-love-slots-do-you--4h5d</guid>
      <description>&lt;p&gt;When building Vue applications, components are the backbone of your UI. But what happens when you need a component that isn’t just reusable but also highly customizable? Enter &lt;strong&gt;Vue slots&lt;/strong&gt;—a powerful feature that lets you define placeholders inside components, allowing you to pass in custom content while maintaining reusability.&lt;/p&gt;

&lt;p&gt;Vue slots provide unmatched flexibility, making it easy to create dynamic, adaptable components. Whether you need to inject content into a modal, customize the layout of a card, or pass complex UI structures into child components, slots make it effortless. They also promote separation of concerns, ensuring that parent components control layout and logic while child components focus on rendering content.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore:&lt;br&gt;
✅ Named and scoped slots for advanced use cases&lt;br&gt;
✅ Dynamics slot names&lt;br&gt;
✅ Scoped slots with functions&lt;/p&gt;

&lt;p&gt;By the end, you'll see how slots can help you write cleaner, more maintainable code while boosting the versatility of your components. &lt;br&gt;
The code is hosted &lt;a href="https://github.com/obiwanpelosi/vue-slots-demo" rel="noopener noreferrer"&gt;here &lt;/a&gt;so you can follow along. Let’s dive in!&lt;/p&gt;

&lt;p&gt;Consider the &lt;code&gt;UserList.vue&lt;/code&gt; component below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { onMounted, ref } from "vue";

const userList = ref([]);
const loading = ref(true);

async function fetchUsers(){
    try {
        const response = await fetch("https://randomuser.me/api/?results=10");
        const data = await response.json();
        userList.value = data.results;
    } catch (error) {
        console.error("Error fetching data: ", error);
    } finally {
        loading.value = false;
    }
}
onMounted(() =&amp;gt; {
  setTimeout(() =&amp;gt; {
    fetchUsers();
  }, 2000);
});
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;slot name="title"&amp;gt;Users&amp;lt;/slot&amp;gt;
    &amp;lt;slot
      name="userlist"
      :list="userList"
      v-if="!loading &amp;amp;&amp;amp; userList.length"
    &amp;gt;
      &amp;lt;ul class="userlist"&amp;gt;
        &amp;lt;li v-for="item in userList" :key="item.email" class="list-item"&amp;gt;
          &amp;lt;div&amp;gt;
            &amp;lt;img
              width="48"
              height="48"
              :src="item.picture.large"
              :alt="item.name.first + ' ' + item.name.last"
            /&amp;gt;
            &amp;lt;div&amp;gt;
              &amp;lt;div&amp;gt;{{ item.name.first }}&amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
    &amp;lt;/slot&amp;gt;
    &amp;lt;slot v-if="loading" name="loading"&amp;gt;Loading...&amp;lt;/slot&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;style scoped&amp;gt;
ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 1em;
}
li.list-item &amp;gt; div {
  display: flex;
  gap: 1em;
}
li img {
  border-radius: 50%;
  width: 50px;
  height: 50px;
}&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a simple component that fetches a list of users when it mounts. You can also see three main slots sections : &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;userlist&lt;/code&gt; and &lt;code&gt;loading&lt;/code&gt;. They all have fallback content, so rendering this component as it is is gonna look like: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;App.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import UserList from "./components/UserList.vue";
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;UserList /&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the browser, you should see: &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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzvin147weth7m8fflxxn.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzvin147weth7m8fflxxn.png" alt="user list with avatar and first names" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is barely scratching the surface, for each slot sections, we can define new templates for them wherever needed. So we could change the title to be more descriptive or even insert a new component there. Let's go ahead and do that, let's also pass the number of users to the new title component: &lt;/p&gt;

&lt;p&gt;Receive the count as a prop in &lt;code&gt;ListTitle.vue&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
const props = defineProps({
  count: Number,
});
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;section&amp;gt;
    &amp;lt;h1&amp;gt;My incredible list of {{ count }} users&amp;lt;/h1&amp;gt;
  &amp;lt;/section&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;style scoped&amp;gt;
section {
  background-color: #f0f0f0;
  padding: 20px;
  border-radius: 5px;
  margin: 20px 0;
}
h1 {
  color: #333;
}
&amp;lt;/style&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assign the user list length to a variable from the &lt;code&gt;title&lt;/code&gt; slot in &lt;code&gt;UserList.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;slot name="title" :count="userList.length"&amp;gt;Users&amp;lt;/slot&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in &lt;code&gt;App.vue&lt;/code&gt;, access the count variable from the slot and pass it as a prop to the &lt;code&gt;ListTitle&lt;/code&gt; component like so :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;UserList&amp;gt;
    &amp;lt;template #title="{ count }"&amp;gt;
      &amp;lt;ListTitle :count="count" /&amp;gt;
    &amp;lt;/template&amp;gt;
  &amp;lt;/UserList&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your browser, you should have: &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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu279x9m7kc4eu4xc2pgi.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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu279x9m7kc4eu4xc2pgi.png" alt="List of users with new title slot" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take it even further, let's modify &lt;code&gt;UserList.vue&lt;/code&gt;. Add a remove function to remove users from the list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function remove(item) {
  userList.value = userList.value.filter(
    (user) =&amp;gt; user.login.uuid !== item.login.uuid
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's also modify the &lt;code&gt;userlist&lt;/code&gt; slot to look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;slot
      name="userlist"
      :list="userList"
      :remove="remove"
      v-if="!loading &amp;amp;&amp;amp; userList.length"
    &amp;gt;
      &amp;lt;ul class="userlist"&amp;gt;
        &amp;lt;li v-for="item in userList" :key="item.email" class="list-item"&amp;gt;
          &amp;lt;slot name="listitem" :user="item"&amp;gt;
            &amp;lt;div&amp;gt;
              &amp;lt;img
                width="48"
                height="48"
                :src="item.picture.large"
                :alt="item.name.first + ' ' + item.name.last"
              /&amp;gt;
              &amp;lt;div&amp;gt;
                &amp;lt;div&amp;gt;{{ item.name.first }}&amp;lt;/div&amp;gt;
                &amp;lt;slot name="secondrow" :item="item"&amp;gt;&amp;lt;/slot&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/slot&amp;gt;
        &amp;lt;/li&amp;gt;
      &amp;lt;/ul&amp;gt;
    &amp;lt;/slot&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we're now also passing the remove function to the slot data. Now we can access the list items and the function to remove items from the list as well. Let's see how we can implement that, let's create a new &lt;code&gt;CardListComponent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
const { list } = defineProps({
  list: Array,
});
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;ul class="userlist"&amp;gt;
    &amp;lt;li v-for="item in list" :key="item.email"&amp;gt;
      &amp;lt;slot name="listitem" :user="item"&amp;gt;
        &amp;lt;div class="card"&amp;gt;
          &amp;lt;img
            class="resposive"
            :src="item.picture.large"
            :alt="item.name.first + ' ' + item.name.last"
          /&amp;gt;
          &amp;lt;div class="card-body"&amp;gt;
            &amp;lt;p&amp;gt;{{ item.name.first }} {{ item.name.first }}&amp;lt;/p&amp;gt;
            &amp;lt;p&amp;gt;{{ item.email }}&amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/slot&amp;gt;
    &amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;style scoped&amp;gt;
ul{
  list-style-type: none;
}
.userlist {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr 1fr 1fr;
}

.resposive {
  width: 100%;
}

.card {
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.25);
  border-radius: 4px;
  overflow: hidden;
}

.card-body {
  padding: 1rem;
}
&amp;lt;/style&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;App.vue&lt;/code&gt; we now have access to the list array and remove function from the userlist slot. We can pass the list to the as a prop to the CardList component like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;UserList&amp;gt;
    &amp;lt;template #title="{ count }"&amp;gt;
      &amp;lt;ListTitle :count="count" /&amp;gt;
    &amp;lt;/template&amp;gt;
    &amp;lt;template #userlist="{ list, remove }"&amp;gt;
      &amp;lt;CardList :list="list"&amp;gt; &amp;lt;/CardList&amp;gt;
    &amp;lt;/template&amp;gt;
  &amp;lt;/UserList&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take it &lt;strong&gt;even further&lt;/strong&gt;, let's modify the &lt;code&gt;CardList.vue&lt;/code&gt; component to have slots and let's make it dynamic. So instead of just rendering the first name, last name and email of the user. let's add the ability to choose what to render using slots. &lt;/p&gt;

&lt;p&gt;Modify the card body in CardList.vue to look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card-body"&amp;gt;

            &amp;lt;slot name="first" :text="item.name.first"&amp;gt;&amp;lt;/slot&amp;gt;

            &amp;lt;slot name="last" :text="item.name.last"&amp;gt;&amp;lt;/slot&amp;gt;

            &amp;lt;slot name="full" :text="`${item.name.first} ${item.name.last}`"&amp;gt;&amp;lt;/slot&amp;gt;

            &amp;lt;slot name="fullWithTitle" :text="`${item.name.title} ${item.name.first} ${item.name.last}`"&amp;gt;&amp;lt;/slot&amp;gt;

            &amp;lt;slot name="secondrow" :item="item"&amp;gt;&amp;lt;/slot&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in App.vue, add a &lt;strong&gt;selected&lt;/strong&gt; ref and &lt;strong&gt;options&lt;/strong&gt; array and bind the value of &lt;strong&gt;selected&lt;/strong&gt; to the slot name inside of the &lt;code&gt;CardList.vue&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const selected = ref("first");

const options = [
  { value: "first", label: "First Name" },
  { value: "last", label: "Last Name" },
  { value: "full", label: "Full name" },
  { value: "fullWithTitle", label: "Name with title" },
];

&amp;lt;template&amp;gt;
  &amp;lt;select v-model="selected"&amp;gt;
    &amp;lt;option
      v-for="(option, index) in options"
      :key="index"
      :value="option.value"
    &amp;gt;
      {{ option.label }}
    &amp;lt;/option&amp;gt;
  &amp;lt;/select&amp;gt;
  &amp;lt;UserList&amp;gt;
    &amp;lt;template #title="{ count }"&amp;gt;
      &amp;lt;ListTitle :count="count" /&amp;gt;
    &amp;lt;/template&amp;gt;
    &amp;lt;template #userlist="{ list }"&amp;gt;
      &amp;lt;CardList :list="list"&amp;gt;
        &amp;lt;template #[selected]="{ text }"&amp;gt;
          &amp;lt;h2&amp;gt;{{ text }}&amp;lt;/h2&amp;gt;
        &amp;lt;/template&amp;gt;

      &amp;lt;/CardList&amp;gt;
    &amp;lt;/template&amp;gt;
  &amp;lt;/UserList&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when a user selects the option with the value of "first", the line &lt;code&gt;template #[selected]&lt;/code&gt; evaluates to &lt;code&gt;template #first&lt;/code&gt; and the first name of the users is rendered on the page. &lt;/p&gt;

&lt;p&gt;We can also modify the App.vue to include the remove function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template #userlist="{ list, remove }"&amp;gt;
      &amp;lt;CardList :list="list"&amp;gt;
        &amp;lt;template #[selected]="{ text }"&amp;gt;
          &amp;lt;h2&amp;gt;{{ text }}&amp;lt;/h2&amp;gt;
        &amp;lt;/template&amp;gt;
        &amp;lt;template #secondrow="{ item }"&amp;gt;
          &amp;lt;button @click="remove(item)"&amp;gt;Remove User&amp;lt;/button&amp;gt;
        &amp;lt;/template&amp;gt;
      &amp;lt;/CardList&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using Vue slots effectively allows for highly flexible and reusable components. In this example, we started with a simple UserList.vue component and progressively enhanced it by introducing slots for customization. We saw how named and scoped slots can help control the rendering of dynamic content and pass necessary data between parent and child components.&lt;/p&gt;

&lt;p&gt;By structuring components in this way, we achieved:&lt;br&gt;
✅ A customizable title component (ListTitle.vue) that dynamically updates with the number of users.&lt;br&gt;
✅ A flexible CardList.vue component that allows users to choose how to display names using slots.&lt;br&gt;
✅ A dynamic way to modify and interact with the rendered list, including removing users.&lt;/p&gt;

&lt;p&gt;This pattern is powerful because it enables component composition without tightly coupling logic and UI. You can reuse and extend these components for various applications, making your Vue.js projects more maintainable and scalable.🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Custom Events in the Browser: A Handy Tool You Didn't Know You Needed</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Mon, 27 Jan 2025 19:16:20 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/custom-events-in-the-browser-a-handy-tool-you-didnt-know-you-needed-4eb9</link>
      <guid>https://dev.to/obiwanpelosi/custom-events-in-the-browser-a-handy-tool-you-didnt-know-you-needed-4eb9</guid>
      <description>&lt;p&gt;Up until recently, I had no idea you could create custom events in the browser. Yes, you read that right—you &lt;strong&gt;can create and dispatch your own custom events&lt;/strong&gt; and listen for them in your application. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Custom Events?
&lt;/h2&gt;

&lt;p&gt;Let me share a use case to explain. I was working on a Chrome extension built with React. The extension consisted of multiple modules, each with its own isolated logic. Some of this logic lived outside React components, in standalone TypeScript files. I needed a way to communicate between these isolated modules and my React app.&lt;/p&gt;

&lt;p&gt;While I can't disclose all the details about the extension, imagine you're building a service for car manufacturers, and you're working with Toyota, Ford, and Mercedes. Each manufacturer requires unique handling, so you end up with separate logic files for each. These files aren't React components, so you can't use tools like &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;React context&lt;/code&gt;, or global state managers like &lt;code&gt;Redux&lt;/code&gt;or &lt;code&gt;MobX&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Faced with this challenge, I explored various solutions. That's when I discovered custom events.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do Custom Events Work?
&lt;/h2&gt;

&lt;p&gt;Custom events allow you to create, dispatch, and listen for events with custom data. Here's the basic syntax:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding a Listener&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;window.addEventListener(type, listener);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt;: A case-sensitive string that represents the event's name.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;listener&lt;/code&gt;: A function that runs when the event is dispatched.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also pass an optional options object to &lt;code&gt;addEventListener&lt;/code&gt;. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener" rel="noopener noreferrer"&gt;Read more about that here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dispatching an Event&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const event = new CustomEvent(eventName, { detail });
window.dispatchEvent(event);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;eventName&lt;/code&gt;: The name of the custom event (must match the type used in &lt;code&gt;addEventListener&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;detail&lt;/code&gt;: An object containing additional parameters to be passed to the listener.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;detail&lt;/code&gt; object makes custom events incredibly powerful because you can send any data to the event listener.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example: Using Custom Events in React
&lt;/h2&gt;

&lt;p&gt;Here’s how I implemented custom events in my Chrome extension:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set Up the Event Listener
I declared the event listener in a &lt;code&gt;useEffect&lt;/code&gt;in my &lt;code&gt;App.tsx&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
    const handleCustomEvent = (event: CustomEvent&amp;lt;{ key: string; value: any }&amp;gt;) =&amp;gt; {
        console.log(event.detail);
    };

    window.addEventListener(ADD_CUSTOM_EVENT, handleCustomEvent as EventListener);

    return () =&amp;gt; {
        window.removeEventListener(ADD_CUSTOM_EVENT, handleCustomEvent as EventListener);
    };
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ADD_CUSTOM_EVENT&lt;/code&gt;: is the event name (declared as a constant to avoid typos).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;handleCustomEvent&lt;/code&gt;: is the listener function, which logs the event's detail object in this example.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Dispatch the Event 
From anywhere in your app, you can dispatch the event like this:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const event = new CustomEvent('ADD_CUSTOM_EVENT', { detail: { key: 'exampleKey', value: 'exampleValue' } });
window.dispatchEvent(event);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why I Love This Approach
&lt;/h2&gt;

&lt;p&gt;With custom events, I was able to easily trigger and handle events across different parts of my app. It provided a simple and elegant solution for cross-module communication without relying on React-specific tools like context or state management libraries.&lt;/p&gt;

&lt;p&gt;I hope this helps someone else as much as it helped me. Custom events are a versatile tool for solving complex communication problems in web applications. Until next time—happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>react</category>
    </item>
    <item>
      <title>Understanding the Importance of res.ok in Fetch API</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Tue, 10 Dec 2024 09:06:47 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/understanding-the-importance-of-resok-in-fetch-api-4a7c</link>
      <guid>https://dev.to/obiwanpelosi/understanding-the-importance-of-resok-in-fetch-api-4a7c</guid>
      <description>&lt;p&gt;I've always been an avid user of Axios for data fetching, but I recently decided to use the Fetch API instead. While exploring it, I encountered a subtle but significant difference that I thought was worth sharing.&lt;/p&gt;

&lt;p&gt;Let’s start with this snippet of code. What do you think it logs?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try{
   //this returns a 404 error
   const res = await fetch("randomapi....") 
   console.log("successful")
  }catch(err){
   console.log("failed", err)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you guessed it would log &lt;code&gt;"failed"&lt;/code&gt; along with the error object to the console, you’re not alone—I thought the same thing until recently. However, that’s not how Fetch works!&lt;/p&gt;

&lt;p&gt;Here’s the catch: even if the Fetch request receives a 404 or 500 status code, it doesn’t throw an error and doesn’t trigger the &lt;code&gt;catch&lt;/code&gt; block. Instead, the &lt;code&gt;fetch&lt;/code&gt; function resolves the promise, leaving it to you to check whether the response was successful.&lt;/p&gt;

&lt;p&gt;To correctly handle errors with Fetch, you need to explicitly check the &lt;code&gt;res.ok&lt;/code&gt; property, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try{
    //returns 404 error
    const res = await fetch("randomapi")
    if(!res.ok){
      throw new Error("fetch request failed")
    }
    console.log("successful")
    let data = await res.json()
    console.log(data)
}catch(err){
  console.log(err)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this approach, if the response status is outside the successful range (200–299), the &lt;code&gt;throw&lt;/code&gt; statement is executed, and the error is caught in the catch block.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Does This Happen?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike Axios, Fetch doesn’t consider HTTP response codes outside of the 2xx range to be errors. Instead, it treats all HTTP responses, successful or not, as fulfilled promises. This design choice gives developers more control but also requires extra effort to handle errors correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding &lt;code&gt;response.ok&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;response.ok&lt;/code&gt; property is a boolean that evaluates to &lt;code&gt;true&lt;/code&gt;for HTTP status codes between &lt;code&gt;200&lt;/code&gt;and &lt;code&gt;299&lt;/code&gt;. For any other status code, it evaluates to &lt;code&gt;false&lt;/code&gt;. This makes it an easy and reliable way to check whether your fetch request was successful.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;200&lt;/code&gt; status indicates success and will set &lt;code&gt;response.ok&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;404&lt;/code&gt; status (not found) or &lt;code&gt;500&lt;/code&gt;status (server error) will set 
&lt;code&gt;response.ok&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also access the status code directly using &lt;code&gt;response.status&lt;/code&gt; if you need more granular error handling, like distinguishing between a client-side error (4xx) and a server-side error (5xx).&lt;/p&gt;

&lt;p&gt;Thanks for reading and I hope this helps someone out there!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Common Vue.js Development Mistakes and How to Avoid Them: Part 3 ✅</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Wed, 25 Oct 2023 09:25:47 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/common-vuejs-development-mistakes-and-how-to-avoid-them-part-3-16eh</link>
      <guid>https://dev.to/obiwanpelosi/common-vuejs-development-mistakes-and-how-to-avoid-them-part-3-16eh</guid>
      <description>&lt;p&gt;Welcome to the third installment of our series on common Vue.js development pitfalls. In this part, we're going to unravel another intriguing challenge – "&lt;strong&gt;Watching Arrays&lt;/strong&gt;."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x-BPWlBp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lz8jduw9pswua43o2yks.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x-BPWlBp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lz8jduw9pswua43o2yks.jpg" alt="magnifying glass on computer screen" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demystifying Array Watching in Vue 3&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Watching arrays in Vue 3 can sometimes be tricky. Have you ever tried to watch an array, confident that your syntax is spot-on, only to find that the watcher doesn't trigger as expected until you add &lt;code&gt;{deep: true}&lt;/code&gt;? If you've experienced this, you're not alone. But rest assured, there's a reason behind this behavior, and it's time to shed some light on it.&lt;/p&gt;

&lt;p&gt;Consider the seemingly straightforward code snippet below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { ref, watch } from "vue";

const numArr = ref([]);
const addRandom = () =&amp;gt; {
  numArr.value.push(Math.random());
};

watch(numArr, () =&amp;gt; {
  console.log("random number added");
});
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;button @click="addRandom"&amp;gt;Add a random number to the array&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'd expect that when you click the button, a random number should be added to the &lt;code&gt;numArr&lt;/code&gt; array, and since we're watching the array, the console should log "random number added," right?&lt;/p&gt;

&lt;p&gt;Well, here's where things get interesting: this won't work as expected 😧. &lt;/p&gt;

&lt;p&gt;Yes, the random number is added to the array. You would then ask if the array is changing and it is being watched for changes, why the heck isn't it working 🤬🤬??&lt;/p&gt;

&lt;p&gt;You can experiment with the code and witness the changes in behavior by using this &lt;a href="https://codesandbox.io/s/admiring-bush-2kh5w2?file=/src/App.vue:0-314"&gt;CodeSandbox&lt;/a&gt; playground. &lt;/p&gt;

&lt;p&gt;Now let's add the &lt;code&gt;deep: true&lt;/code&gt; option to the watcher and see what happens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { ref, watch } from "vue";

const numArr = ref([]);
const addRandom = () =&amp;gt; {
  numArr.value.push(Math.random());
};

watch(numArr, () =&amp;gt; {
  console.log("random number added");
}, 
{deep: true});
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;button @click="addRandom"&amp;gt;Add a random number to the array&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this adjustment, you'd notice that the callback is now working as expected. But why does this make a difference? It's a valid question.&lt;/p&gt;

&lt;p&gt;The key lies in understanding how Vue.js watches arrays. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When you replace an array entirely, you don't need to use the &lt;code&gt;deep&lt;/code&gt;option. However, in scenarios where you're mutating the array, such as adding or removing items, or modifying existing elements, the deep option is essential.&lt;br&gt;
 It ensures that Vue.js watches for changes within the array's elements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If we were to replace the entire array, we could achieve our goal without the &lt;code&gt;deep&lt;/code&gt;option. Here's an example of how you can modify our code to replace the array in its entirety:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { ref, watch } from "vue";

const numArr = ref([]);
const addRandom = () =&amp;gt; {
  numArr.value = [...numArr, Math.random()]
};

watch(numArr, () =&amp;gt; {
  console.log("random number added");
});
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;button @click="addRandom"&amp;gt;Add a random number to the array&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this approach is effective, some might find it less intuitive compared to simply using the &lt;code&gt;push&lt;/code&gt; method and enabling the &lt;code&gt;deep&lt;/code&gt; option. Additionally, what adds an extra layer of complexity is the fact that in Vue 2, you didn't need to use the &lt;code&gt;deep&lt;/code&gt; option for this purpose.&lt;/p&gt;

&lt;p&gt;However, according to &lt;a href="https://v3-migration.vuejs.org/breaking-changes/watch.html"&gt;Vue 3 migration guides&lt;/a&gt;, this change was introduced as a breaking change. In Vue 3,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"when watching an array, the callback will only trigger when the array is replaced. If you need to trigger on mutation, the &lt;code&gt;deep&lt;/code&gt; option must be specified.&lt;br&gt;
"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So there you have it, if you find that your callbacks aren't firing as expected, the first thing to check is whether you've included the &lt;code&gt;deep&lt;/code&gt; option in your watcher. This simple addition can make a significant difference in how your Vue 3 application handles array watching.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>vue</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Common Vue.js Development Mistakes and How to Avoid Them: Part 2 ✅</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Wed, 18 Oct 2023 18:33:55 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/common-vuejs-development-mistakes-and-how-to-avoid-them-part-2-4hco</link>
      <guid>https://dev.to/obiwanpelosi/common-vuejs-development-mistakes-and-how-to-avoid-them-part-2-4hco</guid>
      <description>&lt;p&gt;Do you ever find yourself in a situation where you're passing a prop to a component, and then passing that same prop to a child component, and then to a grandchild component? If so, you've encountered a common challenge in Vue.js development known as "&lt;strong&gt;prop drilling.&lt;/strong&gt;" &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3yqB-cct--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2p1eimou4wjmh6trueyu.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3yqB-cct--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2p1eimou4wjmh6trueyu.jpeg" alt="prop drilling demo" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what exactly is prop drilling, and why is it considered an anti-pattern in Vue.js? The same issue can also arise with event emitting, creating what's known as "event tunneling." Both of these techniques, prop drilling and event tunneling, can make your code less intuitive and harder to maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prop Drilling in Vue.js:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Prop drilling occurs when you pass a prop through multiple levels of nested components to reach its final destination. While Vue's component-based architecture encourages reusability and modularity, this practice can lead to complexities that make your codebase less elegant and maintainable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event Tunneling in Vue.js:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, event tunneling happens when you emit an event from a deeply nested child component and then capture and handle that event at a higher-level parent component. This can also result in code that's challenging to follow, as it breaks the clear data flow that Vue.js promotes.&lt;/p&gt;

&lt;p&gt;So, how can we avoid these anti-patterns and make our Vue.js code more efficient and easier to maintain?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Solution 1: Use &lt;code&gt;provide&lt;/code&gt; and &lt;code&gt;inject&lt;/code&gt; in Vue.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TEy3dlgZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujcy8z1zb82siy6hbmqm.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TEy3dlgZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujcy8z1zb82siy6hbmqm.jpeg" alt="Provide/Inject demo" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One effective method to combat prop drilling and event tunneling in Vue.js is by leveraging the built-in feature called &lt;code&gt;provide&lt;/code&gt; and &lt;code&gt;inject&lt;/code&gt;. This powerful duo allows you to provide data at a higher component level and then inject that data deep down the component tree, regardless of how many nested levels you have. Read the docs &lt;a href="https://vuejs.org/guide/components/provide-inject.html#prop-drilling"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A noteworthy example of this pattern in action is &lt;code&gt;Vue Router&lt;/code&gt;. It provides the router and route objects throughout your application by offering them at the App component level and injecting them into each individual component. This approach eliminates the need to accept route or router props in every single component, leading to a cleaner and more maintainable codebase.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--arscDRPq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jz07t7x3roki3ifavk0y.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--arscDRPq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jz07t7x3roki3ifavk0y.jpeg" alt="Example of provide/inject being used in the vue-router docs" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By embracing &lt;code&gt;provide&lt;/code&gt; and &lt;code&gt;inject&lt;/code&gt;, you can ensure that data flows seamlessly through your Vue.js application, reducing the need for excessive prop passing and event emitting. This not only enhances code readability but also simplifies the maintenance of your components, making your development journey smoother and more efficient.&lt;/p&gt;

&lt;p&gt;The syntax for using &lt;code&gt;provide&lt;/code&gt; and &lt;code&gt;inject&lt;/code&gt; in Vue.js is quite straightforward. In the parent component, you call the &lt;code&gt;provide&lt;/code&gt; function with two parameters: an identifier (known as the injection key) and the data you want to pass down. Here's a snippet of code illustrating this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;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="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;provide&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Child&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Child.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;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get Lunch&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;Play Ball&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;Check Todo&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;Call John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nx"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todoList&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Child&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&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;In this example, we're providing a list of todos with the identifier "todoList" using the &lt;code&gt;provide&lt;/code&gt; function. This data can now be injected into the &lt;code&gt;Child&lt;/code&gt; component, making it accessible there without the need for prop chaining or event emission. This method simplifies the data flow and improves the maintainability of your Vue.js application. Every direct or indirect descendant of this component will have access to this data using the &lt;code&gt;inject&lt;/code&gt; function like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;shuffle&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lodash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todoList&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;shuffleItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;todos&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;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todos&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="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&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;"todo in todos"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"JSON.stringify(todo)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&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;span class="nt"&gt;&amp;lt;button&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;"shuffleItems"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Shuffle Items&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&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 really believe this is an under-utilized feature in Vue.js and I don't see it often.&lt;br&gt;
You can check out and play around with this concept in &lt;a href="https://codesandbox.io/s/musing-swirles-gvsr7j?file=/src/components/Parent.vue"&gt;this sandbox environment&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution 2: Use a global state management option&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using Vue's global state management tools is another powerful solution to address the challenges of prop drilling and event tunneling in your Vue.js applications. Instead of maintaining state at a higher-level component and passing it down, global state management enables you to store and manage the state outside of the components themselves. This makes the state accessible in any component within your application, enhancing flexibility and maintainability.&lt;/p&gt;

&lt;p&gt;There are several options available for global state management in Vue.js, including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Composables:&lt;/strong&gt; Vue 3 introduced Composition API, which includes the use of composable functions to manage and share state across components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vuex:&lt;/strong&gt; Vuex is a popular state management library for Vue.js, designed specifically for managing application-level state and actions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pinia:&lt;/strong&gt; Pinia is a state management solution recommended by the Vue.js core team. It offers a robust and highly efficient way to manage state in Vue applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While I won't delve into the specific details of each option here, I encourage you to explore the documentation for these tools to choose the one that best suits your project's needs. Global state management is a powerful strategy that not only mitigates prop drilling and event tunneling but also empowers you to build scalable and maintainable Vue.js applications. &lt;/p&gt;

&lt;p&gt;For a more in-depth understanding of each tool, consider referring to their respective documentation (&lt;a href="https://vuex.vuejs.org/guide/"&gt;vuex&lt;/a&gt;, &lt;a href="https://pinia.vuejs.org/"&gt;pinia&lt;/a&gt;, &lt;a href="https://vuejs.org/guide/reusability/composables.html"&gt;composables&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;That wraps up this article on common Vue.js pitfalls! Stay tuned for the next part, where we'll delve into yet another common mistake in Vue.js development. See you in the next article, and happy coding! 💻🥳&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Common Vue.js Development Mistakes and How to Avoid Them ✅</title>
      <dc:creator>Obiwan Pelosi</dc:creator>
      <pubDate>Mon, 16 Oct 2023 10:59:48 +0000</pubDate>
      <link>https://dev.to/obiwanpelosi/common-vuejs-development-mistakes-and-how-to-avoid-them-4k60</link>
      <guid>https://dev.to/obiwanpelosi/common-vuejs-development-mistakes-and-how-to-avoid-them-4k60</guid>
      <description>&lt;p&gt;Vue.js, a popular and developer-friendly JavaScript framework, has gained a well-deserved reputation for its ease of use and efficiency. However, as with any technology, there are common pitfalls that developers can stumble upon. In this series of articles, we will explore some of the frequent mistakes that can lead to unforeseen bugs and tricky issues in Vue.js development.&lt;/p&gt;

&lt;p&gt;Having worked with Vue.js for a significant amount of time, I’ve personally encountered and wrestled with these issues in numerous projects. Some of them, I didn’t even realize were problems until they caused headaches 😅. Now that I’ve learned from these experiences, I want to share the solutions with you to make your development journey smoother and bug-free.&lt;/p&gt;

&lt;p&gt;The goal of this article is to help you understand and avoid these common Vue.js pitfalls, saving you time and frustration in your development process. So, let’s delve into these issues and learn from my mistakes, ensuring that you never make them in the first place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common Mistake #1: Omitting the Key Attribute in v-for Iteration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the most common pitfalls in Vue.js development is omitting the &lt;code&gt;key&lt;/code&gt; attribute when using &lt;code&gt;v-for&lt;/code&gt; to iterate over a list of items. Let’s take a look at the code snippet below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzngxcbkovwu3kt243r1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzngxcbkovwu3kt243r1.jpeg" alt="v-for without key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, we’re iterating over the &lt;code&gt;**items**&lt;/code&gt; array using &lt;code&gt;**v-for**&lt;/code&gt;, but Vue.js requires that each iterated element has a unique &lt;code&gt;**key**&lt;/code&gt; attribute. This is crucial for Vue to efficiently update the DOM when items are added, removed, or reordered. If you have ESLint properly set up, you’ll receive an immediate warning, indicated by a red underline beneath the v-for line. When you hover over this warning, you'll see a message like "&lt;strong&gt;Element in iteration expected to have '&lt;/strong&gt;v-bind:key*&lt;em&gt;' directive.&lt;/em&gt;*"&lt;/p&gt;

&lt;p&gt;In this article, our primary goal is to delve deeper into why omitting the &lt;code&gt;**key**&lt;/code&gt; attribute in Vue.js is problematic and help you gain a comprehensive understanding of this issue. To demonstrate the significance of the &lt;code&gt;**key**&lt;/code&gt; attribute, let’s begin by binding it to a unique identifier for each item within the &lt;code&gt;**items**&lt;/code&gt; array. In this example, we’ll use the &lt;code&gt;**id**&lt;/code&gt; field, a common and widely accepted practice when iterating over items from a database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9a24iyi5sksplqmbl7ud.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9a24iyi5sksplqmbl7ud.jpeg" alt="v-for with key"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you’ll observe, the moment we introduce the &lt;code&gt;**key**&lt;/code&gt; attribute, the red warning indicator vanishes. However, let’s take a moment to grasp the significance of this seemingly subtle change. What have we truly achieved by incorporating this unique key into our Vue.js components?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/strange-heisenberg-v6msm2?file=/src/components/KeyExample.vue" rel="noopener noreferrer"&gt;&lt;strong&gt;Try it out&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When dealing with static data, the absence of the &lt;code&gt;**key**&lt;/code&gt; attribute might not be immediately evident. However, as soon as we begin working with elements and components that have their own state, this problem becomes apparent. In our current scenario, we’re dealing with an HTML input element tied to a reactive value.&lt;/p&gt;

&lt;p&gt;Now, let’s reintroduce the &lt;code&gt;**key**&lt;/code&gt; attribute and give shuffling another try. You’ll observe a stark difference — the labels and inputs are now perfectly synchronized and move in harmony with each other as they are shuffled.&lt;/p&gt;

&lt;p&gt;Great, you’ve now experienced firsthand the importance of always including a &lt;code&gt;**key**&lt;/code&gt; attribute in your &lt;code&gt;**v-for**&lt;/code&gt; loops. While it might seem unnecessary when working with static data or items that don’t maintain state or require reordering, it’s a critical practice to adopt.&lt;/p&gt;

&lt;p&gt;Applications have a tendency to evolve and grow, and what might seem inconsequential today could become a source of random and challenging-to-debug errors in the future. Therefore, it’s a best practice to consistently provide the &lt;code&gt;**key**&lt;/code&gt; attribute to ensure your Vue.js components can handle state changes and reordering gracefully, even as your application scales and complexity increases. By doing so, you’re proactively guarding against potential issues and ensuring a smoother development journey.&lt;/p&gt;

&lt;p&gt;Let’s discuss the significance of choosing the right key value for your &lt;code&gt;**v-for**&lt;/code&gt; loops. In some cases, even if you provide a key, you may not fully address the issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❗❗ ️Avoid using the index as the key:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One common mistake I frequently encounter is the usage of the index as the key in a &lt;code&gt;**v-for**&lt;/code&gt; loop, as demonstrated below:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;ul&amp;gt;&lt;br&gt;
 &amp;lt;li v-for="(item, index) in items" :key="index"&amp;gt;{{ item.label }} &amp;lt;input type="text" /&amp;gt;&amp;lt;/li&amp;gt;&lt;br&gt;
 &amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If we attempt to shuffle this list, you’ll notice that we encounter the same problem as if we didn’t use a key at all. To compound the issue, most IDEs won’t flag this as an error or provide any red warnings, making it even more challenging to detect the problem. Feel free to try filling in an input and shuffling the list again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/broken-wind-zvt26n?file=/src/components/KeyExample.vue" rel="noopener noreferrer"&gt;&lt;strong&gt;Try it out&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key lesson here is straightforward: ❌ avoid using the index as the key. Instead, you should provide a key that is unique to each specific item, rather than relying on its position in the list, which can change. Typically, this unique key is an ‘&lt;strong&gt;id&lt;/strong&gt;’, but if an ‘&lt;strong&gt;id&lt;/strong&gt;’ is unavailable, you should make the best choice based on the available data. In our example, since all the labels are unique, they could also serve as keys. Additionally, you can pass a combination of ‘&lt;strong&gt;ids&lt;/strong&gt;’ and ‘&lt;strong&gt;labels&lt;/strong&gt;’ or even stringify the entire object, as demonstrated below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Combination of IDs and Labels ✅:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;li v-for="item in items" :key="item.id + item.label"&amp;gt;{{ item.label }} &amp;lt;input type="text" /&amp;gt;&amp;lt;/li&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stringifying the Entire Object ✅:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;li v-for="item in items" :key="JSON.stringify(item)"&amp;gt;{{ item.label }} &amp;lt;input type="text" /&amp;gt;&amp;lt;/li&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By choosing a key that is genuinely unique to each item, you ensure that Vue.js can accurately track and update your components, avoiding any unexpected issues in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;In wrapping up, we’ve uncovered the significance of the &lt;code&gt;**key**&lt;/code&gt; attribute in Vue.js development and the pivotal role it plays in ensuring smooth and efficient reactivity. By understanding both the “&lt;strong&gt;how&lt;/strong&gt;” and “&lt;strong&gt;why&lt;/strong&gt;” behind adding the &lt;code&gt;**key**&lt;/code&gt; attribute, you’re equipped to create robust and bug-free applications.&lt;/p&gt;

&lt;p&gt;However, our exploration of common Vue.js pitfalls doesn’t end here. Stay tuned for our next article, where we’ll delve into another prevalent mistake in Vue.js development, providing you with valuable insights to enhance your Vue.js skills. In the meantime, remember to apply the lessons learned here and make your Vue.js projects more reliable and scalable.&lt;/p&gt;

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