<?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: timothyokooboh</title>
    <description>The latest articles on DEV Community by timothyokooboh (@timothyokooboh).</description>
    <link>https://dev.to/timothyokooboh</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%2F332337%2F73835f37-980e-4111-b743-617ca06f767b.png</url>
      <title>DEV Community: timothyokooboh</title>
      <link>https://dev.to/timothyokooboh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/timothyokooboh"/>
    <language>en</language>
    <item>
      <title>What I Learned From Building A UI Components Library For Legacy And Modern Vue.js Applications</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Tue, 24 Jun 2025 05:54:58 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/what-i-learned-from-building-a-ui-components-library-for-legacy-and-modern-vuejs-applications-4aj</link>
      <guid>https://dev.to/timothyokooboh/what-i-learned-from-building-a-ui-components-library-for-legacy-and-modern-vuejs-applications-4aj</guid>
      <description>&lt;p&gt;I had the pleasure of leading a team of frontend engineers to build an internal library of reusable and accessible UI components based on our design system. We had to implement over 40 UI components and each needed to meet acceptable standards for accessibility, reusability, and maintenance. The UI library needed to cater to the needs of both legacy products that are based on Vue 2 and more recent products that are based on Vue 3.&lt;/p&gt;

&lt;p&gt;In this article, I would like to share the lessons I learned from that experience and the decisions and tradeoffs we had to make. Here is a summary of the lessons I learned from building an internal library of design system components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build on top of open-source, headless UI libraries when you can.&lt;/li&gt;
&lt;li&gt;Prioritize web accessibility.&lt;/li&gt;
&lt;li&gt;Be guided by a set of software engineering best practices.&lt;/li&gt;
&lt;li&gt;Define and document a component’s architecture before development.&lt;/li&gt;
&lt;li&gt;Test components in real-world usage, not just in isolation.&lt;/li&gt;
&lt;li&gt;Create well-written documentation for developers on how to use the new UI library.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let’s get into the details!&lt;/p&gt;

&lt;h2&gt;
  
  
  Build on top of open-source, headless UI libraries when you can.
&lt;/h2&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%2Fw8nxa7304oshvf55omkd.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%2Fw8nxa7304oshvf55omkd.png" alt="Radix UI" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Building design system components is not an easy task, especially when you consider accessibility requirements and some edge cases in functionality. This is why building on top of open-source libraries that have taken care of important aspects, such as functionality and accessibility, would be a great way to start. Popular libraries such as &lt;a href="https://www.radix-vue.com/" rel="noopener noreferrer"&gt;Radix UI&lt;/a&gt;, &lt;a href="https://headlessui.com/v1/vue/menu" rel="noopener noreferrer"&gt;Headless UI&lt;/a&gt;, and &lt;a href="https://primevue.org/" rel="noopener noreferrer"&gt;PrimeVue&lt;/a&gt; are top of the list, at least in the Vue ecosystem. These libraries provide ways to customize the theme and styles of components using your brand colors, typography, etc., and get accessibility and functionality for free.&lt;/p&gt;

&lt;p&gt;However, my team and I did not build on top of a headless UI library. Instead, we built the components from scratch. One thing that all popular and actively maintained open-source headless UI libraries, such as Radix-UI, Headlessui, and PrimeVue, have in common is that they only support Vue 3. They don’t support Vue 2.&lt;/p&gt;

&lt;p&gt;I pointed out earlier that some of our products are legacy systems based on Vue 2. So to address this challenge, we first built components in Vue 2 to support the legacy apps, then created a Vue 3 version of the same component to support the Vue 3 apps, ensuring that both variants share the same API. This consistency in API made it easy to write one documentation that supports both the Vue 2 and Vue 3 variants of the same component. Also, since engineers can be rotated across different product teams, consistency in API ensures that engineers don’t have to learn a new API when working on a product that uses the Vue 3 or Vue 2 components, which is great for developer experience.&lt;/p&gt;

&lt;p&gt;JavaScript libraries such as &lt;a href="https://floating-ui.com/" rel="noopener noreferrer"&gt;floating-ui&lt;/a&gt; and &lt;a href="https://atomiks.github.io/tippyjs/" rel="noopener noreferrer"&gt;tippy.js&lt;/a&gt; were very helpful in building components such as tooltips, popovers, and dropdowns. Packages such as &lt;a href="https://www.npmjs.com/package/tabbable" rel="noopener noreferrer"&gt;tabbable&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/focus-trap-vue" rel="noopener noreferrer"&gt;focus-trap-vue&lt;/a&gt; were helpful in implementing a keyboard-accessible modal.&lt;/p&gt;

&lt;p&gt;Building on top of an open-source headless library would have been a great choice. However, in software engineering, it’s important to understand fundamentals and learn how things work under the hood so that you can still get the job done when there is a good reason to build from scratch.&lt;/p&gt;

&lt;p&gt;In hindsight, probably a much better approach would have been to develop the component library as web components by leveraging frameworks such as &lt;a href="https://lit.dev/" rel="noopener noreferrer"&gt;Lit Elements&lt;/a&gt; or &lt;a href="https://stenciljs.com/" rel="noopener noreferrer"&gt;Stencil.js&lt;/a&gt;. That way, instead of maintaining two variants of the same component, we would only have one library of web components that can be used across products irrespective of the JavaScript framework the products are built with. From my experience, components built with Vue.js or React.js make it easy to craft a better developer experience compared to web components. However, software engineering is mostly about trade-offs, and by allocating more time for development, it’s possible to build a robust UI library of web components that can serve the needs of enterprise applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prioritize web accessibility.
&lt;/h2&gt;

&lt;p&gt;In addition to writing semantic HTML, one of the easiest ways to build an accessible application is to ensure that the UI building blocks are accessible. This is why accessibility is at the core of any open-source UI library. If an open-source UI library does not prioritize accessibility, the web community will frown at it. This is why &lt;a href="https://adrianroselli.com/2025/05/do-not-publish-your-designs-on-the-web-with-figma-sites.html" rel="noopener noreferrer"&gt;Figma sites have been getting a lot of criticisms related to accessibility violations&lt;/a&gt;. Despite how important and challenging building complex accessible experiences can be, you get accessibility for free if you leverage standard open-source UI libraries, as mentioned earlier.&lt;/p&gt;

&lt;p&gt;Since we built our components from scratch, that made implementing accessibility even more challenging and interesting. To help my team get accessibility right, I shared &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/" rel="noopener noreferrer"&gt;this resource that contains accessibility guidelines for building many design system components&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxjjeb41wdbmzghe47yaw.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%2Fxjjeb41wdbmzghe47yaw.png" alt="Image description" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, courses on frontend masters related to accessibility were very helpful. If you are interested, check out &lt;a href="https://frontendmasters.com/courses/enterprise-accessibility/" rel="noopener noreferrer"&gt;Enterprise Web App Accessibility&lt;/a&gt; and &lt;a href="https://frontendmasters.com/courses/accessibility-v3/" rel="noopener noreferrer"&gt;Web Accessibility, v3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can leverage &lt;a href="https://chromewebstore.google.com/detail/arc-toolkit/chdkkkccnlfncngelccgbgfmjebmkmce" rel="noopener noreferrer"&gt;arc toolkit chrome extension&lt;/a&gt; to perform accessibility testing. You can press &lt;code&gt;CMD + Shift + C&lt;/code&gt; on a Mac or &lt;code&gt;Ctrl + Shift + C&lt;/code&gt; on Windows to quickly inspect accessibility properties of an element.&lt;/p&gt;

&lt;p&gt;The takeaway is that when building UI components, prioritise accessibility, not just aesthetics. The web community rewards what works for all, not just what looks good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be guided by a set of software engineering best practices.
&lt;/h2&gt;

&lt;p&gt;When building a project, it's necessary for the codebase to be guided by a set of software engineering best practices. Below are some of the guiding principles I emphasised before we commenced development.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Atomic design: Components were designed in a modular, reusable fashion, breaking down complex components into smaller, manageable building blocks. For instance, below is a sample usage of our Tabs component.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;SfeTabs default-tab="tab1" variant="shadowButton"&amp;gt;
  &amp;lt;SfeTabList&amp;gt;
      &amp;lt;SfeTabTrigger value="tab1"&amp;gt;Tab 1&amp;lt;/SfeTabTrigger&amp;gt;
      &amp;lt;SfeTabTrigger value="tab2"&amp;gt;Tab 2&amp;lt;/SfeTabTrigger&amp;gt;
      &amp;lt;SfeTabTrigger value="tab3"&amp;gt;Tab 3&amp;lt;/SfeTabTrigger&amp;gt;
  &amp;lt;/SfeTabList&amp;gt;

  &amp;lt;SfeTabContent value="tab1"&amp;gt;
      &amp;lt;p&amp;gt;Content for Tab 1&amp;lt;/p&amp;gt;
  &amp;lt;/SfeTabContent&amp;gt;
  &amp;lt;SfeTabContent value="tab2"&amp;gt;
      &amp;lt;p&amp;gt;Content for Tab 2&amp;lt;/p&amp;gt;
  &amp;lt;/SfeTabContent&amp;gt;
  &amp;lt;SfeTabContent value="tab3"&amp;gt;
      &amp;lt;p&amp;gt;Content for Tab 3&amp;lt;/p&amp;gt;
  &amp;lt;/SfeTabContent&amp;gt;
&amp;lt;/SfeTabs&amp;gt;

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

&lt;/div&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%2Fgc4yppfev1ow3cco05s0.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%2Fgc4yppfev1ow3cco05s0.png" alt="Tabs component with shadowButton variant" width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I spent time going through &lt;a href="https://chakra-ui.com/" rel="noopener noreferrer"&gt;Chakra UI&lt;/a&gt; and &lt;a href="https://www.shadcn-vue.com/" rel="noopener noreferrer"&gt;Shadcn&lt;/a&gt; to get inspiration on how to compose complex components. &lt;a href="https://vuejs.org/guide/components/provide-inject.html" rel="noopener noreferrer"&gt;Vue’s provide/inject &lt;/a&gt;played a critical role in allowing us to break down components such as Tabs, Accordion, Breadcrumb, Dropdown, etc., into a set of related, tightly coupled components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single responsibility principle: Each component had a clear, focused responsibility, ensuring clean and maintainable code.&lt;/li&gt;
&lt;li&gt;Reusability: Components were built to be reused across different projects and contexts, reducing redundancy and effort. &lt;a href="https://michaelnthiessen.com/reusable-components" rel="noopener noreferrer"&gt;I recommend this course&lt;/a&gt; by Michael Thiessen on reusable components.&lt;/li&gt;
&lt;li&gt;Declarative programming: We focused on describing what the UI should look like rather than how to build it, making the code easier to reason about and understand.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Define and document a component’s architecture before development.
&lt;/h2&gt;

&lt;p&gt;Before developing a new component myself or assigning a task to an engineer, I documented the component’s architecture on Notion to specify its usage, props, slots, custom events, and accessibility criteria. It made development easier, as my team and I could discuss about a component’s API and make necessary adjustments before development.&lt;/p&gt;

&lt;p&gt;For example, this is a section of a draft of the Select component architecture&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%2Fqfrxvxrotfzfxwczgf7i.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%2Fqfrxvxrotfzfxwczgf7i.png" alt="draft of select component architecture" width="800" height="728"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Test components in real-world usage, not just in isolation.
&lt;/h2&gt;

&lt;p&gt;One of the lessons I learned the hard way was the importance of testing components both in isolation and in real-world usage to see how a component integrates with other components.&lt;/p&gt;

&lt;p&gt;For example, in a real-world application, the Select component will be used inside a form alongside other components such as Input, Checkbox, Radio buttons, etc. While each of these components should be tested in isolation, they should also be tested in the context of how they will be used together in production.&lt;/p&gt;

&lt;p&gt;Testing the Select component in isolation would be fine. But testing it inside a form can let you know if the component works well with form validation rules. For instance, does clicking the submit button trigger an error state on the Select component if no option has been selected from its dropdown menu despite the validation rule specifying that at least one option must be selected?&lt;/p&gt;

&lt;p&gt;Also, testing the Select component inside a modal can help you test that its dropdown menu is not confined to the height of the modal.&lt;/p&gt;

&lt;p&gt;Testing in isolation reveals bugs; testing in integration reveals design flaws. So it’s important to test in both contexts.&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%2Fong7ik6y5238xdko2cv1.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%2Fong7ik6y5238xdko2cv1.png" alt="Select component" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create well-written documentation for developers on how to use the new UI library.
&lt;/h2&gt;

&lt;p&gt;Creating well-written documentation is as important as developing the components. Engineers should not have to study the source code just to learn how to use your components. &lt;/p&gt;

&lt;p&gt;To improve adoption and developer experience, we created documentation that showcased example usage of each component. We also created an API reference section for each component, highlighting its props, slots, and events. We were able to create one documentation since both the Vue 2 and Vue 3 variants of each component exposed the same API.&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%2F4vxkzz37q8af8vlib0ps.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%2F4vxkzz37q8af8vlib0ps.png" alt="Image description" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://www.npmjs.com/package/prismjs" rel="noopener noreferrer"&gt;prism.js&lt;/a&gt; to create a basic syntax highlighting component and &lt;a href="https://www.npmjs.com/package/copy-to-clipboard" rel="noopener noreferrer"&gt;copy-to-clipboard&lt;/a&gt; to implement a ‘copy code to clipboard’ functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
/*
  Takes the 'language' and 'code' props and returns the same code with syntax higlighting, with support for HTML (markup), JavaScript and CSS.
*/
highlightCode() {
 if(this.language === 'markup') {
    return Prism.highlight(this.code, Prism.languages.markup, 'markup');
  } else if(this.language === 'javascript') {
    return Prism.highlight(this.code, Prism.languages.javascript, 'javascript');
  } 
  return Prism.highlight(this.code, Prism.languages.css, 'css'); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Leading development of 40+ reusable and accessible components for use across both legacy and modern codebases was a demanding and rewarding experience. At the core of our decisions were accessibility and developer experience. Prioritizing accessibility from day one, treating documentation as a first-class deliverable, testing components both in terms of isolation and integration , and maintaining a unified API across both the Vue 2 and Vue 3 components were critical to the success of the project.&lt;/p&gt;

</description>
      <category>designsystem</category>
      <category>a11y</category>
      <category>vue</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Six Factors That Raise The Risk Of Bugs In A Codebase</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Mon, 04 Mar 2024 06:58:42 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/six-factors-that-raise-the-risk-of-bugs-in-a-codebase-4hlk</link>
      <guid>https://dev.to/timothyokooboh/six-factors-that-raise-the-risk-of-bugs-in-a-codebase-4hlk</guid>
      <description>&lt;p&gt;As a frontend developer, I've come across several key factors that greatly impact the presence of bugs in a codebase. While my insights are based on JavaScript applications, these principles are relevant across different codebases. Let's explore them together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Lack of Static Code Analysis&lt;/strong&gt;&lt;br&gt;
Static code analysis tools like &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; and &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt; play a crucial role in identifying and preventing bugs. TypeScript provides static typing, enhancing the robustness of the code. ESLint detects issues and enforces coding standards. The absence of these tools can significantly elevate the likelihood of bugs due to the lack of early detection and guidance provided during development.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example of TypeScript usage&lt;/span&gt;
&lt;span class="c1"&gt;// Define a function with static typing&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Lack of Automated Testing&lt;/strong&gt;&lt;br&gt;
Codebases devoid of automated tests, such as unit and end-to-end tests, are at risk of too many bugs. Without automated tests, the detection of regressions and bugs relies heavily on manual testing, leaving room for oversight and undetected issues. Consequently, developers may hesitate to introduce changes or refactor existing code, fearing unintended consequences. When working on a codebase that lacks automated tests, it becomes really hard to ship new features with confidence.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// sample unit test with jest&lt;/span&gt;
&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;adds 1 + 2 to equal 3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// sample end to end test with playwright&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;porfolio page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/portfolio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

 &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;can view the tech jobs project&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;techjobs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3000/portfolio/techjobs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Lack of a Continuous Integration Build Process&lt;/strong&gt;&lt;br&gt;
Codebases lacking a continuous integration (CI) build process miss out on automated checks for production readiness, code quality, and test coverage. Without CI, discrepancies between developer environments and the production environment may lead to undetected bugs surfacing in production. Depending on where your code repository is located, you can setup a CI workflow using &lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;, &lt;a href="https://bitbucket.org/product/features/pipelines" rel="noopener noreferrer"&gt;Bitbucket Pipelines&lt;/a&gt;, &lt;a href="https://docs.gitlab.com/ee/ci/" rel="noopener noreferrer"&gt;Gitlab CI&lt;/a&gt; etc.&lt;/p&gt;

&lt;p&gt;Example of a GitHub Action workflow that checks the formatting of files, builds for production, checks linting and runs test cases&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;develop&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;develop&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cache dependencies&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;check formatting of files&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn format:check&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build for production&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn build&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;check linting of files&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn lint&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;run unit tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yarn test:unit&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Misleading Variable or Function Names&lt;/strong&gt;&lt;br&gt;
A variable or function is considered misleading if its name does not accurately reflect its functionality. This discrepancy can lead to bugs when developers rely on the function's name to guide their implementation logic. For instance, consider the function &lt;code&gt;isLoggedIn&lt;/code&gt;. One would expect it to return true if a user is logged in and false otherwise. However, imagine if the function returns a user object when a user is logged in and null otherwise. While a user object is a truthy value and null is a falsy value, such discrepancies in return types can result in unintended bugs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Better&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isLoggedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;OR&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isLoggedIn&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="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Misleading&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isLoggedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Multiple Sources of Truth for the Same State&lt;/strong&gt;&lt;br&gt;
Having multiple sources of truth for the same state can lead to bugs that are hard to trace or debug. It introduces inconsistency and confusion into the codebase, making it difficult to maintain and debug issues. Consider the example below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Vue.js&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loanBalance&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loanBalance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getLoanBalance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/loans/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nx"&gt;loanBalance&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateLoanBalance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;loanBalance&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;balance&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component above has three sources of truth for the state &lt;code&gt;loanBalance&lt;/code&gt;: the input field (two-way data binding), the &lt;code&gt;getLoanBalance&lt;/code&gt; function, and the &lt;code&gt;updateLoanBalance&lt;/code&gt; function. When a state is modified in many places, such multiple side effects can lead to bugs that are hard to trace and debug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Redundant States&lt;/strong&gt;&lt;br&gt;
A component contains redundant states if the same value is stored in more than one state. This becomes problematic if you have to &lt;em&gt;manually&lt;/em&gt; keep track of the states and ensure they contain the same value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Vue.js&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;subscribers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
 &lt;span class="nl"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&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;notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt; 
   &lt;span class="na"&gt;subscribers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
   &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscribers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getNotification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/notifications&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="nx"&gt;notification&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="nx"&gt;subscribers&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;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribers&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, the list of subscribers is contained in both the notification state and the subscribers state. Having to manually ensure that both states contain the same value can lead to bugs.&lt;/p&gt;

&lt;p&gt;However, if subscribers need to be accessed across multiple places in the component, it is much better to use a computed property to ensure that you don't have to manually synchronize the values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="c1"&gt;// Vue.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt; 
   &lt;span class="na"&gt;subscribers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
   &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscribers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// React&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNotification&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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;subscribers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribers&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribers&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In conclusion, the pursuit of bug-free code is an ongoing endeavor. Throughout this article, we've explored six key factors that contribute to the proliferation of bugs within a codebase. From the absence of static code analysis and automated testing infrastructure to the presence of misleading variable names and duplicate states, each factor presents its own set of challenges and risks. By acknowledging these factors and implementing strategies to mitigate their impact, developers can strive towards building more robust and resilient software applications.&lt;/p&gt;

</description>
      <category>bugs</category>
      <category>architecture</category>
      <category>patterns</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Seven Lessons I Have Learned From My Experience as a Software Developer</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Mon, 06 Mar 2023 18:59:01 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/seven-lessons-i-have-learned-from-my-experience-as-a-software-developer-2hfk</link>
      <guid>https://dev.to/timothyokooboh/seven-lessons-i-have-learned-from-my-experience-as-a-software-developer-2hfk</guid>
      <description>&lt;p&gt;I decided to change career from pharmacy to software engineering in 2018, which has changed my life forever. Since that time, I've had the chance to work on a range of projects, either independently or as a member of a cross-functional team.&lt;/p&gt;

&lt;p&gt;Despite the fact that I have not been around for a very long time, I have discovered and seen a few factors that consistently lead to positive outcomes. I have also noticed the actions that don't result in the desired results.&lt;/p&gt;

&lt;p&gt;I'll thus be sharing some lessons I've learned from my time spent working as a frontend engineer. These are my opinions. The ideas I present in this post have been shown to yield positive outcomes. I'd be interested to hear your opinions if you disagree with any of them, though. This article aims to impart some important lessons I've discovered that might be useful to others. I will therefore be glad to benefit from your experiences as well.&lt;/p&gt;

&lt;p&gt;Well, with that said, let's get started!&lt;/p&gt;

&lt;p&gt;A. &lt;em&gt;&lt;strong&gt;If you understand the problem then you are 50% done even before writing the first line of code.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As software developers, our daily work revolves around finding solutions to challenges. Hence, when faced with an issue at work, it can be tempting to want to write code right away and provide answers. &lt;/p&gt;

&lt;p&gt;If you are certain that you already comprehend the issue you are trying to tackle, then this is acceptable. But it turns out that this isn't true the majority of the time. Before attempting to write code to address a problem, it is crucial to make sure you have a thorough understanding of the problem and you know what success looks like.&lt;/p&gt;

&lt;p&gt;This approach has some advantages such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It helps to solve the root cause and not the symptoms of the problem.&lt;/li&gt;
&lt;li&gt;It helps to come up with a more robust and maintainable solution.&lt;/li&gt;
&lt;li&gt;It prevents you from wasting your time and that of your colleagues&lt;/li&gt;
&lt;li&gt;It saves resources in the long run&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most crucial lesson I've learned as a frontend engineer, in my opinion, is to fully comprehend the issue before writing any code!&lt;/p&gt;

&lt;p&gt;Reading the technical/product specifications, asking the appropriate team member questions to clear up any confusions, doing internet research on the issue, etc., are all strategies for comprehending the problem you want to solve.&lt;/p&gt;

&lt;p&gt;B. &lt;strong&gt;&lt;em&gt;Be a team player. It's about institution and not individual.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Being a proficient and dependable software engineer is crucial. But playing well with others is just as crucial!&lt;/p&gt;

&lt;p&gt;Being a team player and acting with humility at work go hand in hand. Never assume that because you have a task or feature to work on, it is because you are the most qualified for it. Someone else on your team might be able to perform the task better. Forget the reason why, then. Instead, concentrate on doing your best to provide a high-quality outcome.&lt;/p&gt;

&lt;p&gt;To be a good team player, you must also communicate with your teammates, support them, and provide them quick feedback.&lt;/p&gt;

&lt;p&gt;C. &lt;strong&gt;&lt;em&gt;Consume quality content&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Online resources are abundant for learning how to code. These are generally all free. Some of the paid resources are affordable, while others are pricey.&lt;/p&gt;

&lt;p&gt;Yet, I've come to understand that quality, not price, should be the deciding factor when selecting a tutorial or course to enroll in.&lt;/p&gt;

&lt;p&gt;Some questions to help assess the quality of a content includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who is the author?&lt;/li&gt;
&lt;li&gt;How many people have subscribed to the course?&lt;/li&gt;
&lt;li&gt;What are the reviews from those who are already taking the course/tutorial?&lt;/li&gt;
&lt;li&gt;What is the average rating?&lt;/li&gt;
&lt;li&gt;When was the the course published? &lt;/li&gt;
&lt;li&gt;When was it last updated?&lt;/li&gt;
&lt;li&gt;Does it contain updated syntax, APIs, and concepts?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a Frontend Engineer, I have found certain platforms and tutors who are known for publishing quality content. They include &lt;a href="https://frontendmasters.com/" rel="noopener noreferrer"&gt;Frontend Masters&lt;/a&gt;, Framework documentation sites (e.g &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt; and &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt;), &lt;a href="https://vueschool.io/" rel="noopener noreferrer"&gt;Vue School&lt;/a&gt;, &lt;a href="https://www.vuemastery.com/" rel="noopener noreferrer"&gt;Vue Mastery&lt;/a&gt;, &lt;a href="https://scrimba.com/" rel="noopener noreferrer"&gt;Scrimba&lt;/a&gt;, and courses by &lt;a href="https://michaelnthiessen.com/" rel="noopener noreferrer"&gt;Michael Thiessen&lt;/a&gt;, &lt;a href="https://www.udemy.com/user/maximilian-schwarzmuller/" rel="noopener noreferrer"&gt;Maximilian Schwarzmuller&lt;/a&gt; and The &lt;a href="https://www.youtube.com/@NetNinja" rel="noopener noreferrer"&gt;Net Ninja&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course, the list is not all-inclusive, but you get the idea.&lt;/p&gt;

&lt;p&gt;D. &lt;strong&gt;&lt;em&gt;Avoid a toxic work culture and a toxic boss!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I won't focus too much on this. But it's vitally significant. &lt;/p&gt;

&lt;p&gt;When I'm considering joining a new company, the work culture is the first thing I consider, not the compensation. I'm not sure about you, but I work best in settings that value a healthy work-life balance, a culture of respect for others, and an open-door policy for employees to express their opinions and be creative.&lt;/p&gt;

&lt;p&gt;E. &lt;strong&gt;&lt;em&gt;The code should be based on the experience of the product. The product should be based on the experience of the user.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The lesson from this point is simple: &lt;code&gt;The development of a software product should be user centric&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
It's crucial for software developers to code with the user in mind. In this manner, you can develop empathy and be motivated to implement simple and enjoyable user interfaces. Also, you can speak with the product manager or tech lead if you notice that a product or technical requirement won't contribute to making users' lives easier.&lt;/p&gt;

&lt;p&gt;F. &lt;em&gt;&lt;strong&gt;Testing is not only for QA engineers.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's crucial to test the code you create. In addition to designing clear and manageable code, testing your code ensures the dependability of the final output.&lt;/p&gt;

&lt;p&gt;In light of this, I believe you should &lt;code&gt;write clean code as if you won't test, then test carefully as if you don't trust your code.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;G. &lt;em&gt;&lt;strong&gt;Take breaks&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Taking breaks at intervals can boost productivity. Taking short intermittent breaks as you code can help manage stress and prevent burn out.&lt;/p&gt;

&lt;p&gt;I have also noticed that sometimes all you need to figure out the solution to a coding challenge or bug fix is to take a break. You'll be mentally prepared to take on the challenge once more when you return to the code. And occasionally, during your break, you might have an epiphany, after which you can quickly return to your code and succeed in the task at hand 😎&lt;/p&gt;

&lt;p&gt;That's it! The seven important lessons I have learned while working as a frontend engineer. &lt;/p&gt;

&lt;p&gt;Do you agree or disagree on any of these points? Would you like to share the lessons from your own experience? It will be nice to know what you think.&lt;/p&gt;

&lt;p&gt;Thank you for reading 😊&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>discuss</category>
      <category>career</category>
      <category>programming</category>
    </item>
    <item>
      <title>Vue.js: How to maintain atomic design principles when using vendor components</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Wed, 21 Apr 2021 19:50:06 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/vue-js-how-to-maintain-atomic-design-principles-when-using-vendor-components-2hf0</link>
      <guid>https://dev.to/timothyokooboh/vue-js-how-to-maintain-atomic-design-principles-when-using-vendor-components-2hf0</guid>
      <description>&lt;p&gt;In this post, I explain how you can maintain atomic design principles when using UI component libraries such as Vuetify, Quasar, BootstrapVue, Font awesome, etc.&lt;/p&gt;

&lt;h6&gt;
  
  
  A brief overview of atomic design principles
&lt;/h6&gt;

&lt;p&gt;Atomic design principles were introduced by &lt;a href="https://bradfrost.com/" rel="noopener noreferrer"&gt;Brad Frost&lt;/a&gt;. He recommends a way of coding up web user interfaces by first breaking them down into the smallest units called &lt;em&gt;atoms&lt;/em&gt;. Then organize a group of atoms into &lt;em&gt;molecules&lt;/em&gt; which can be reused in &lt;em&gt;organisms&lt;/em&gt;. A group of &lt;em&gt;organisms&lt;/em&gt; can be put together to form a &lt;em&gt;template&lt;/em&gt; (without the real content). And when real content is placed inside templates, you get &lt;em&gt;pages.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For example, let's say you want to create a form component. &lt;br&gt;
By following the atomic design principles, you could have a component for inputs &lt;em&gt;BaseInput.vue&lt;/em&gt;. A component for labels &lt;em&gt;BaseLabel.vue&lt;/em&gt;. And a button component &lt;em&gt;BaseButton.vue&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Each of these components would constitute your atoms. Then your form component could look like this.&lt;/p&gt;
&lt;h4&gt;
  
  
  AppForm.vue
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The focus of this post is not to deeply explain atomic design principles. To learn more, check out &lt;a href="https://atomicdesign.bradfrost.com/chapter-2/" rel="noopener noreferrer"&gt;chapter 2 of the book &lt;/a&gt;. Also, in this article, &lt;a href="https://vuedose.tips/how-to-structure-a-vue-js-app-using-atomic-design-and-tailwindcss" rel="noopener noreferrer"&gt;Alba Silvente&lt;/a&gt;, dives deeper into how you can apply atomic design principles in Vue.js.&lt;/p&gt;

&lt;h6&gt;
  
  
  Vendor component wrapper design pattern
&lt;/h6&gt;

&lt;p&gt;The vendor component wrapper design pattern can be used to maintain atomic design principles when using component libraries like Vuetify.&lt;/p&gt;

&lt;p&gt;It encourages wrapping vendor components (e.g Vuetify, BootstrapVue, Quasar, Font awesome) inside your own custom &lt;em&gt;.vue&lt;/em&gt; components.&lt;/p&gt;

&lt;p&gt;By the way, I learned about this design pattern from &lt;a href="https://twitter.com/bencodezen" rel="noopener noreferrer"&gt;Ben Hong&lt;/a&gt;, a Vue.js core team member in &lt;a href="https://frontendmasters.com/courses/production-vue/" rel="noopener noreferrer"&gt;this course&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's do a comparison of how our code could look like if we are to create a form component with Vuetify without applying this design pattern versus if we apply this design pattern.&lt;/p&gt;

&lt;h4&gt;
  
  
  Without applying vendor component wrapper design pattern
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;AppForm.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
   
&lt;h4&gt;
  
  
  With vendor component wrapper design pattern
&lt;/h4&gt;

&lt;p&gt;With vendor component wrapper design pattern, you will need to create your own &lt;em&gt;.vue&lt;/em&gt; components that &lt;strong&gt;wrap&lt;/strong&gt; the individual vuetify component. &lt;/p&gt;
&lt;h4&gt;
  
  
  BaseInput.vue
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  BaseButton.vue
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;For &lt;em&gt;Vue 3.0&lt;/em&gt;, no need to add &lt;em&gt;v-on="listeners"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By setting &lt;code&gt;v-bind = "$attrs" and v-on="$listeners"&lt;/code&gt;, you can pass all the props and attributes specified in the vendor component's API reference to your own &lt;em&gt;.vue&lt;/em&gt; components, just as you would have done directly on the vendor components.&lt;/p&gt;

&lt;p&gt;Note: If your template has a wrapping container element, e.g a &lt;em&gt;div&lt;/em&gt; element, you will need to set &lt;em&gt;inheritAttrs&lt;/em&gt; to false&lt;/p&gt;

&lt;h4&gt;
  
  
  BaseInput.vue
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Then our form component will look like this:&lt;/p&gt;

&lt;h4&gt;
  
  
  AppForm.vue
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Advantages of this pattern
&lt;/h4&gt;

&lt;p&gt;(i) By wrapping vendor components inside your own &lt;em&gt;.vue components&lt;/em&gt;, you can have finite control over vendor components API and still maintain atomic design principles just as you would have done if you were designing all your UI components with CSS, SCSS, or Tailwind CSS.&lt;/p&gt;

&lt;p&gt;(ii) Your components can be flexible enough to switch between displaying vendor components or your own custom-made UI components.&lt;/p&gt;

&lt;p&gt;In this example, I can switch between displaying a Vuetify button or display the button I designed myself with CSS&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The &lt;em&gt;isVuetify&lt;/em&gt; prop can be used to determine which button gets displayed.&lt;/p&gt;

&lt;p&gt;You can even extend this methodology to switch between two vendor components e.g Font awesome icons or Material design icons.&lt;/p&gt;

&lt;p&gt;That will not be possible if you do not wrap vendor components inside of your own &lt;em&gt;.vue components&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Vuex best practices</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Wed, 14 Apr 2021 18:55:20 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/vuex-best-practices-45dd</link>
      <guid>https://dev.to/timothyokooboh/vuex-best-practices-45dd</guid>
      <description>&lt;p&gt;As a Vue.js developer, I have been using Vuex for state management. &lt;/p&gt;

&lt;p&gt;Recently, I completed a course on Frontend Masters titled &lt;strong&gt;&lt;a href="https://frontendmasters.com/courses/vuex/" rel="noopener noreferrer"&gt;Vuex for intermediate developers&lt;/a&gt;&lt;/strong&gt;. I have also read a couple of useful posts on Vuex written by experienced Vue.js developers.&lt;/p&gt;

&lt;p&gt;Therefore, these days when utilizing Vuex in my application, I do my best to follow these patterns/strategies/rules.&lt;/p&gt;

&lt;p&gt;A. &lt;strong&gt;Always use &lt;em&gt;Mutations&lt;/em&gt; to update a value in Vuex state.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's say you have something like this in your state:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const state = {&lt;br&gt;
  age: 20&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To update the value of &lt;strong&gt;age&lt;/strong&gt; inside any of your Vue components, &lt;strong&gt;never do this:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;this.$store.state.age = 40;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Instead, write a mutation that will be responsible for updating the state.&lt;/p&gt;

&lt;p&gt;You could write something like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const mutations = {&lt;br&gt;
updateAge(state, payload) {&lt;br&gt;
state.age = payload&lt;br&gt;
}&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then in your components, you can do this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;this.$store.commit("updateAge", 40)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can even extend this example further with the next best practice.&lt;/p&gt;

&lt;p&gt;B. &lt;strong&gt;Let every mutation be associated with an action. Then dispatch these actions inside of your Vue components.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most experienced Vue developers propose that components should not directly commit mutations. Instead, every mutation should be associated with an action. Then components should dispatch these actions instead of directly committing mutations.&lt;/p&gt;

&lt;p&gt;To demonstrate this concept with our previous example, let's create an action:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const actions = {&lt;br&gt;
updateAge({ commit }, payload) {&lt;br&gt;
commit("updateAge", payload)&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then inside our Vue components, we will dispatch the action instead of committing the mutation directly.&lt;br&gt;
&lt;code&gt;this.$store.dispatch("updateAge", 40)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;C. &lt;strong&gt;Keep asynchronous logic inside actions and NEVER inside mutations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Asynchronous logic such as fetching data from an API call should be carried out inside actions and not inside mutations. &lt;/p&gt;

&lt;p&gt;This is because each time a mutation updates the Vuex state, it leaves a &lt;em&gt;before&lt;/em&gt; and &lt;em&gt;after&lt;/em&gt; snapshot of the Vuex state inside of Vue dev tools. This is very useful in debugging because you can always go back in time to check the initial values in the state before the mutation was committed.&lt;/p&gt;

&lt;p&gt;But this unique ability of mutations is lost whenever an asynchronous event is fired inside a mutation. Hence it is best to only perform synchronous tasks inside mutations.&lt;/p&gt;

&lt;p&gt;Usually, these synchronous tasks only involve updating the value of the state just like we did before:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;state.age = payload&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;D. &lt;strong&gt;Actions and Mutations should not be used outside of their core responsibilities.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because Vuex actions and mutations are simply javascript functions, sometimes we execute logic that should&lt;br&gt;
not really be done inside either of them.&lt;/p&gt;

&lt;p&gt;Each time you commit a mutation, it should do only ONE thing: &lt;strong&gt;Update the value of the state&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each time you dispatch an action, it should do one or more of the following:&lt;br&gt;
(i) Fetch data from an API.&lt;br&gt;
(ii) Commit a mutation.&lt;br&gt;
(iii) Dispatch an action.&lt;/p&gt;

&lt;p&gt;Each time you find yourself executing logic that falls outside of these core responsibilities, you should consider extracting that logic inside a &lt;strong&gt;Vuex plugin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Thankfully, Vuex plugins are very easy to write. I will show you how.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case&lt;/strong&gt;&lt;br&gt;
Let's say you dispatched an action that fetched data from an API. Then you committed a mutation and passed the API response as a payload to the mutation. Then inside your mutation, you updated the value of the Vuex state with the payload. And in addition, you want to save some values to local storage.&lt;/p&gt;

&lt;p&gt;It's best not to write the logic that saves the values to local storage inside of your mutation or action. Instead, you can write a simple plugin to do just that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to write a plugin&lt;/strong&gt;&lt;br&gt;
Let's create a Vuex plugin to save data in Local storage.&lt;/p&gt;

&lt;p&gt;Create a folder called &lt;strong&gt;plugins&lt;/strong&gt;, preferably inside of your Vuex store folder. Then create a file called &lt;strong&gt;webStorage.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export default function saveToLocalStorage(store) {&lt;br&gt;
 store.subscribe((mutation, state) =&amp;gt; {&lt;br&gt;
if(mutation.type === 'updateState' ) {&lt;br&gt;
const payload = mutation.payload;&lt;br&gt;
localStorage.setItem("userId", payload.userId)&lt;br&gt;
localStorage.setItem("username", payload.username)&lt;br&gt;
}&lt;br&gt;
})&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A Vuex plugin is just a normal javascript function that receives the Vuex store as its only argument.&lt;/p&gt;

&lt;p&gt;In the code above, I check if the mutation that was committed is called "updateState". Then I access the payload from the mutation and save the username and userId to local storage.&lt;/p&gt;

&lt;p&gt;This logic does not update the Vuex state. Therefore, it's not best practice to place it inside of a mutation.&lt;/p&gt;

&lt;p&gt;To use this plugin, we will import it into the Vuex store (index.js file)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;store/index.js&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;import saveToLocalStorage from "plugins/webStorage";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const Store = new Vuex.Store({&lt;br&gt;
plugins: [saveToLocalStorage],&lt;br&gt;
state: {},&lt;br&gt;
mutations: {},&lt;br&gt;
actions: {},&lt;br&gt;
getters: {}&lt;br&gt;
})&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Vuex plugins are really powerful and easy to write. You can use them to create powerful notification systems such as notifying a slack channel whenever a particular mutation or action is executed.&lt;/p&gt;

&lt;p&gt;E. &lt;strong&gt;Don't write redundant code inside Vuex getters.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The below Vuex getter is not really useful and should not have been written in the first place:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const getters: {&lt;br&gt;
getAge(state){&lt;br&gt;
return state.age;&lt;br&gt;
}&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It is only returning the value of age. In our components, we can conveniently access the value of age without the help of this getter.&lt;br&gt;
&lt;code&gt;this.$store.state.age&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use getters to compute derived values of the state&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But let's say we want to check if age is less than 18. Using a getter to &lt;strong&gt;compute&lt;/strong&gt; this value will be very useful.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const getters: {&lt;br&gt;
isUnderAge(state){&lt;br&gt;
return state.age &amp;lt; 18&lt;br&gt;
}&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then inside of our components, we can conveniently determine if a user is under age by accessing the value of the getter:&lt;br&gt;
&lt;code&gt;this.$store.getters.isUnderAge&lt;/code&gt; instead of writing &lt;code&gt;return this.$store.state.age &amp;lt; 18&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's it, guys! ☺️.&lt;br&gt;
Let me know what you think about these tips. And share the best practices you have been applying inside of your Vuex codebase too.&lt;/p&gt;

&lt;p&gt;I must add that these best practices will not be complete without a properly organized Vuex folder structure. But that's a topic for another time.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Vue 3.0: Debugging composable functions</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Sun, 28 Mar 2021 18:29:47 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/vue-3-0-debugging-composable-functions-1h3e</link>
      <guid>https://dev.to/timothyokooboh/vue-3-0-debugging-composable-functions-1h3e</guid>
      <description>&lt;p&gt;The &lt;strong&gt;composition API&lt;/strong&gt; is a core feature of Vue 3.0 (&lt;em&gt;though it is also available as a plugin for Vue 2&lt;/em&gt;). It provides an alternative syntax for writing Vue.js components. Vue developers are used to the options API where each component may consist of one or more options such as data, computed, watchers, mixins, directives, filters, extends, and lifecycle hooks.&lt;/p&gt;

&lt;p&gt;Recently, I have been creating Vue components using the composition API. I must say that it has been an awesome experience. This is because the composition API offers a better and cleaner way of composing &lt;strong&gt;reusable code/logic&lt;/strong&gt; across your Vue application. These reusable codes are commonly referred to as &lt;strong&gt;composable functions&lt;/strong&gt;. You may already be familiar with  &lt;strong&gt;mixins&lt;/strong&gt;. Unlike Vue 2 where mixins were mostly used to create and share reusable logic, &lt;strong&gt;in Vue 3.0 writing composable functions is the real deal!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The purpose of this article is to share with you two mistakes I have made while writing and using composable functions.&lt;/strong&gt; And of course, they caused bugs in my app. They may seem quite trivial but these are potential sources of bugs that you should be aware of.&lt;/p&gt;

&lt;p&gt;To demonstrate how to avoid these gotchas, let's build a simple login component with two logical concerns: &lt;strong&gt;form validation&lt;/strong&gt; and &lt;strong&gt;API consumption&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf2g094s33hld8ol7ktv.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%2Fuf2g094s33hld8ol7ktv.png" alt="login form" width="709" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7tw1m01mbftodlwuh7f.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%2Fi7tw1m01mbftodlwuh7f.png" alt="login form" width="665" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frauyghznyjwxrdz3pry3.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%2Frauyghznyjwxrdz3pry3.png" alt="login form" width="675" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used TailwindCSS for the styling. Don't mind the placeholder text &lt;strong&gt;"Pharmacy email address"&lt;/strong&gt;. The template code is an excerpt from a project I'm working on 😉&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Below is the script section &lt;strong&gt;before refactoring the code to use composable functions&lt;/strong&gt;. As earlier stated, there are two logical concerns: &lt;strong&gt;form validation and API consumption&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
I used &lt;strong&gt;vee-validate&lt;/strong&gt; to validate the user's inputs. With vee-validate's &lt;strong&gt;useField&lt;/strong&gt; method, I created &lt;em&gt;email&lt;/em&gt; and &lt;em&gt;password&lt;/em&gt; fields which are connected to the template via v-model.&lt;br&gt;
With the help of vee-validate's &lt;strong&gt;useForm&lt;/strong&gt; method, I validated the email field to ensure that it is required and is a valid email address. The password must be at least 8 characters long. 

&lt;p&gt;&lt;strong&gt;Now, let's refactor the code to use composable functions!&lt;/strong&gt;. To do so, let's separate each logical concern into its own file.&lt;/p&gt;

&lt;p&gt;For this demo, I placed the validation logic into it's own file.&lt;br&gt;
&lt;strong&gt;demo-validation.js&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;For this demo, I placed the login API call into it's own file.&lt;br&gt;
&lt;strong&gt;demo-login.js&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now, let's make use of these composable functions. To do so, we just have to import them into the component and destructure the values that were returned from the composable functions.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Simple right? 😀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mistakes to avoid&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here are two mistakes you should always avoid: &lt;/p&gt;

&lt;p&gt;a. After importing your composable functions into the component, &lt;strong&gt;Don't forget to invoke them inside the setup function&lt;/strong&gt;. It's not enough to destructure returned values from the composable functions. &lt;strong&gt;You must also add brackets after the functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;const {&lt;br&gt;
            email,&lt;br&gt;
            emailErrorMessage,&lt;br&gt;
            password,&lt;br&gt;
            passwordErrorMessage&lt;br&gt;
        } = FormValidation &lt;strong&gt;()&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;b. When passing arguments to a composable function inside setup, &lt;strong&gt;don't add the "value" key&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;DO THIS&lt;br&gt;
  const {&lt;br&gt;
            loginUser&lt;br&gt;
        } = &lt;strong&gt;Login(email, password)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;INSTEAD OF&lt;br&gt;
  const {&lt;br&gt;
            loginUser&lt;br&gt;
        } = &lt;strong&gt;Login(email.value, password.value)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But to use the arguments inside of the composable function file, you must use the value key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;demo-login.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DO THIS&lt;/p&gt;

&lt;p&gt;const user = await axios.post("/api/users", {&lt;br&gt;
                email: &lt;strong&gt;email.value,&lt;/strong&gt;&lt;br&gt;
                password: &lt;strong&gt;password.value&lt;/strong&gt;&lt;br&gt;
            })&lt;/p&gt;

&lt;p&gt;INSTEAD OF &lt;/p&gt;

&lt;p&gt;const user = await axios.post("/api/users", {&lt;br&gt;
                email: &lt;strong&gt;email,&lt;/strong&gt;&lt;br&gt;
                password: &lt;strong&gt;password&lt;/strong&gt;&lt;br&gt;
            })&lt;/p&gt;

&lt;p&gt;That's it, guys! Leave any comments or questions below. Thanks for reading ☺️&lt;/p&gt;

</description>
    </item>
    <item>
      <title>5 CSS Properties You Probably Did Not Know About</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Sat, 19 Sep 2020 15:23:08 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/5-css-properties-you-probably-did-not-know-about-164i</link>
      <guid>https://dev.to/timothyokooboh/5-css-properties-you-probably-did-not-know-about-164i</guid>
      <description>&lt;p&gt;I have been studying a lot of new CSS properties in order to up my game as a frontend developer.&lt;/p&gt;

&lt;p&gt;I am fascinated by the new CSS properties I have come across and utilized in my recent projects. Therefore, I am going to share 5 CSS properties you probably didn't know about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;a class="mentioned-user" href="https://dev.to/media"&gt;@media&lt;/a&gt; (hover: none) or &lt;a class="mentioned-user" href="https://dev.to/media"&gt;@media&lt;/a&gt;(hover: hover)&lt;/strong&gt;&lt;br&gt;
How do you know if users are viewing your web application with a touch-screen device (e.g mobile phones) or a non-touch-screen device (e.g desktop/laptop)? &lt;/p&gt;

&lt;p&gt;You can determine this by using the media query above.&lt;/p&gt;

&lt;p&gt;This is important because some CSS properties like &lt;strong&gt;hover&lt;/strong&gt; may not be so important when applied to touch screen devices. The hover effect is not so obvious on touch screen devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/media"&gt;@media&lt;/a&gt; all and(hover: none) {&lt;br&gt;
  &lt;em&gt;apply styles for touch screen devices e.g mobile phones&lt;/em&gt;&lt;br&gt;
}&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/media"&gt;@media&lt;/a&gt; all and(hover: hover) {&lt;br&gt;
  &lt;em&gt;apply styles for non-touch-screen devices&lt;/em&gt;&lt;br&gt;
}&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The CSS property in the codepen below will only apply on &lt;em&gt;non-touch-screen devices&lt;/em&gt; when users &lt;strong&gt;hover&lt;/strong&gt; on the text. Therefore, if you are viewing this on your mobile phone, the hover effect will not work.&lt;br&gt;
&lt;iframe height="600" src="https://codepen.io/timopharm/embed/bGpmMKq?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. selection pseudo-class&lt;/strong&gt;&lt;br&gt;
The selection pseudo-class lets you define custom colors and background colors that appear when users try to &lt;strong&gt;copy texts&lt;/strong&gt; on your web applications.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/timopharm/embed/wvGYvwO?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. hyphens&lt;/strong&gt; &lt;br&gt;
By setting the hyphens property to &lt;strong&gt;auto&lt;/strong&gt;, texts on your webpages will be automatically hyphenated.&lt;/p&gt;

&lt;p&gt;In the codepen below, try resizing the browser and see hyphens automatically apply to the texts&lt;br&gt;
&lt;iframe height="600" src="https://codepen.io/timopharm/embed/bGpmMwe?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. background-clip&lt;/strong&gt;&lt;br&gt;
When set to &lt;strong&gt;text&lt;/strong&gt;, the background-clip property is useful for creating linear-gradients on texts.&lt;br&gt;
However, to work on the chrome browser, you need to add the &lt;em&gt;-webkit&lt;/em&gt; prefix.&lt;br&gt;
&lt;iframe height="600" src="https://codepen.io/timopharm/embed/vYGVjWY?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5 @supports&lt;/strong&gt;&lt;br&gt;
This is a very useful CSS property. It lets you set styles that should only apply when a browser supports a CSS property.&lt;/p&gt;

&lt;p&gt;In the codepen below, the &lt;strong&gt;@supports&lt;/strong&gt; property will ensure that the &lt;strong&gt;backdrop-filter&lt;/strong&gt; CSS property will only be applied on browsers that support the property. Hence, if you view the webpage with a browser that doesn't support the property e.g firefox, then the &lt;em&gt;backdrop-filter&lt;/em&gt; won't be applied. You will need to set up a default property that should apply. In this case, I used background-color as the fallback property.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Click the button to view the modal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/timopharm/embed/wvGYjOe?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that's it!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you find any of these CSS properties interesting, please leave a comment below. I'd also love to learn about new CSS properties that you have come across lately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thanks for reading.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Understanding Watchers in Vue.js</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Sat, 11 Jul 2020 15:51:42 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/understanding-watchers-in-vue-js-mki</link>
      <guid>https://dev.to/timothyokooboh/understanding-watchers-in-vue-js-mki</guid>
      <description>&lt;p&gt;In this article, we will take a deep dive into one of the core concepts in Vue.js -- &lt;strong&gt;watchers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We will start from scratch and look at what watchers are and then we will go further to look at two properties available within a watcher: &lt;strong&gt;deep&lt;/strong&gt; and &lt;strong&gt;handler&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We will end the lesson by building a simple project where we will connect to an API endpoint and fetch data to our webpage. Of course, we will use &lt;strong&gt;watchers&lt;/strong&gt; to get the job done. &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/nQzc-F1E5_E"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lets's get started&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open your text editor to code along. I will be using visual studio code. &lt;br&gt;
Let's begin with the following HTML markup.&lt;br&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%2Fm4gu1uv03l8xfumduxoo.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%2Fm4gu1uv03l8xfumduxoo.png" alt="code" width="800" height="385"&gt;&lt;/a&gt;&lt;br&gt;
Then, &lt;a href="https://vuejs.org/v2/guide/installation.html" rel="noopener noreferrer"&gt;head over here to get the Vue.js CDN &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F731oegodannzk2z423iv.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%2F731oegodannzk2z423iv.png" alt="code" width="672" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have included the Vue.js CDN on the project. To test if everything is working fine, I added a property called msg in the data object and outputted it on the DOM. Now go to your browser, you should see &lt;strong&gt;hello timothy&lt;/strong&gt; printed on the webpage. &lt;/p&gt;

&lt;h2&gt;Understanding Watchers&lt;/h2&gt;

&lt;p&gt;In addition to the data object, the Vue instance accepts other properties such as methods, computed properties, watch, filters, and life cycle hooks such as mounted. &lt;/p&gt;

&lt;p&gt;As the name implies, watchers &lt;strong&gt;watch&lt;/strong&gt; for changes in the value of a property that we have already defined in our data object, and &lt;strong&gt;does something&lt;/strong&gt; whenever the value of that property changes. They can also watch for changes in the value of a computed property, and do something whenever the value changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's see how it works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbqpbnebz9pryrqxk5oy.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%2Fxbqpbnebz9pryrqxk5oy.png" alt="code" width="548" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have added a button to the DOM and attached a method to it called changeName which gets executed whenever the button is clicked. Below the button, there is an empty div that has a &lt;strong&gt;ref&lt;/strong&gt; attribute with a value of &lt;strong&gt;name&lt;/strong&gt;. The &lt;strong&gt;ref&lt;/strong&gt; attribute will be used to access this div inside of the Vue instance instead of using traditional javascript methods like &lt;strong&gt;getElementById&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0iytgzmz0ji1dz4i8xq.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%2Fa0iytgzmz0ji1dz4i8xq.png" alt="code" width="376" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, when the button gets clicked, the name changes from &lt;strong&gt;Timothy Okooboh&lt;/strong&gt; to &lt;strong&gt;Julie Peterson&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/cQAy8q_74VY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The next thing we will do is to &lt;strong&gt;watch&lt;/strong&gt; for this change and make something happen whenever the value of name changes.&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%2Fq29j76neef0xbgpygxqn.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%2Fq29j76neef0xbgpygxqn.png" alt="code" width="711" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what is happening here?&lt;br&gt;
We added a &lt;strong&gt;watch&lt;/strong&gt; object to the Vue instance. Then we gave it a property called &lt;strong&gt;name&lt;/strong&gt; which happens to be a function. Within this function, we listened for changes in the value of the &lt;strong&gt;name&lt;/strong&gt; property defined inside of the data object. When a change occurs, we set the innerHTML of the div that has a &lt;strong&gt;ref&lt;/strong&gt; value of &lt;strong&gt;name&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There is one major thing you &lt;strong&gt;MUST&lt;/strong&gt; take note of. The &lt;strong&gt;name&lt;/strong&gt; property within the &lt;strong&gt;watch&lt;/strong&gt; object MUST BE CALLED &lt;strong&gt;name&lt;/strong&gt; and nothing else. Why? you may ask. Well, that is because we are watching for changes in the value of &lt;strong&gt;name&lt;/strong&gt;. If we had an &lt;strong&gt;email&lt;/strong&gt; property within the data object and wanted to watch for it, then we would have called the watcher &lt;strong&gt;email&lt;/strong&gt; and nothing else.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/DgLJ2rOPbtU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Also, the watcher takes two parameters, the first is the &lt;strong&gt;new value&lt;/strong&gt; of the property we are watching. The second parameter is the &lt;strong&gt;old value&lt;/strong&gt; of the property we are watching.&lt;/p&gt;

&lt;h2&gt;Understanding the handler method&lt;/h2&gt;

&lt;p&gt;In our code above, the watcher &lt;strong&gt;name&lt;/strong&gt; was declared as a function. But it can actually be declared as an object. When declared as an object, the watcher can take three properties namely a &lt;strong&gt;handler function&lt;/strong&gt;, and two booleans &lt;strong&gt;deep&lt;/strong&gt; and &lt;strong&gt;immediate&lt;/strong&gt;. For the sake of this article, we will focus on the handler function and deep.&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%2F5geabr9xegna987z8kkj.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%2F5geabr9xegna987z8kkj.png" alt="code" width="727" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the code above, the &lt;strong&gt;handler&lt;/strong&gt; function basically holds the logic that should get executed whenever the value of the property that we are watching for changes. &lt;/p&gt;

&lt;p&gt;Head over to your browser, you should still see that the code works as before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about deep?&lt;/strong&gt;&lt;br&gt;
If you understand &lt;strong&gt;deep&lt;/strong&gt;, then your knowledge of watchers will be on a new level.&lt;/p&gt;

&lt;p&gt;Basically, you use &lt;strong&gt;deep&lt;/strong&gt; when watching for changes in the value of items inside an array, or changes in the value of properties inside an object. You will need to set &lt;strong&gt;deep&lt;/strong&gt; to &lt;strong&gt;true&lt;/strong&gt; in order to tell Vue.js to inspect the contents of arrays and objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's see how it works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoeathy5ennd1jfdzi66.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%2Fdoeathy5ennd1jfdzi66.png" alt="code" width="634" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before I explain what is going on, let's see the Vue instance.&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%2Ffmvcrok515ica1xpjf4a.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%2Ffmvcrok515ica1xpjf4a.png" alt="code" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have an array called &lt;strong&gt;fruits&lt;/strong&gt;. Then we take the value of the user's input and use it to replace the first item in the array. We then watch for this change and try to render &lt;strong&gt;"the first fruit has changed"&lt;/strong&gt; to the DOM&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/-C9J1jT222s"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As you can see, we successfully changed the value of the first item in the array &lt;strong&gt;but the action inside the watcher failed to execute&lt;/strong&gt;. This can be solved by setting &lt;strong&gt;deep&lt;/strong&gt; to &lt;strong&gt;true&lt;/strong&gt; like so &lt;br&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%2F54tjzijtdqbaqc1kq25d.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%2F54tjzijtdqbaqc1kq25d.png" alt="code" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now if you view it on your browser, you will see that Vue.js can now inspect our array and execute the action stated in our watcher.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/h_-mb70Wuh8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;Finally, let's build a simple project&lt;/h2&gt;

&lt;p&gt;We are going to connect to the &lt;strong&gt;yes/no&lt;/strong&gt; API. The way it will work is that our users will type a question inside an input field. Then we will &lt;strong&gt;watch&lt;/strong&gt; for changes in the value of the input field and send a &lt;strong&gt;GET&lt;/strong&gt; request to the API endpoint. Then we will display the result on the webpage. But before sending the request, we will execute a simple validation -- we will check if the user's question ends with a question mark.&lt;/p&gt;

&lt;p&gt;Enough of the talk. Let's see how it works.&lt;/p&gt;

&lt;p&gt;We will use &lt;strong&gt;axios&lt;/strong&gt; for sending the http request. &lt;a href="https://cdnjs.com/libraries/axios" rel="noopener noreferrer"&gt; Head over here to get the axios CDN&lt;/a&gt;&lt;br&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%2Fvdpkbf3euzr3umt44iyg.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%2Fvdpkbf3euzr3umt44iyg.png" alt="code" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the template markup&lt;br&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%2Ffj20kpe7ecwk3a52huxs.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%2Ffj20kpe7ecwk3a52huxs.png" alt="code" width="703" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the data object&lt;br&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%2F5mdlemt0wnr9cvd0mg1z.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%2F5mdlemt0wnr9cvd0mg1z.png" alt="code" width="498" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the method that will send the &lt;strong&gt;GET&lt;/strong&gt; request**&lt;br&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%2Fu33u7ieye670irdcbwbu.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%2Fu33u7ieye670irdcbwbu.png" alt="code" width="572" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then this is our &lt;strong&gt;watcher&lt;/strong&gt; &lt;br&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%2Fpf6egnd11l6n1ygb5xa5.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%2Fpf6egnd11l6n1ygb5xa5.png" alt="code" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our &lt;strong&gt;watcher&lt;/strong&gt; first validates the user's request to check if it ends with a question mark. If the validation passes, it calls the getResult method after 5 seconds.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/nQzc-F1E5_E"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;THANKS FOR READING&lt;/strong&gt;. I hope that you learned something. Kindly leave your comments/questions below.&lt;/p&gt;

</description>
      <category>watchers</category>
      <category>vue</category>
      <category>javascript</category>
    </item>
    <item>
      <title>HOW TO BECOME A BETTER Vue.js DEVELOPER</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Thu, 09 Jul 2020 13:01:49 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/how-to-become-a-better-vue-js-developer-l13</link>
      <guid>https://dev.to/timothyokooboh/how-to-become-a-better-vue-js-developer-l13</guid>
      <description>&lt;p&gt;Hello devs! I want to share some things that I believe can make anyone to level up as a Vue.js developer.&lt;/p&gt;

&lt;p&gt;Few hours ago, I deployed a simple &lt;a href="https://buyhub.herokuapp.com/?#/" rel="noopener noreferrer"&gt; e-commerce  web app&lt;/a&gt; which I made by using Vue on the frontend and node.js/express on the backend.&lt;/p&gt;

&lt;p&gt;Having worked with Vue for a while, I feel I should share some tips with you.&lt;/p&gt;

&lt;p&gt;If you are reading this, it's either you are already working with Vue.js professionally, you just started learning Vue.js, or you are considering learning the framework.&lt;/p&gt;

&lt;p&gt;Whichever category you belong to, I'm sure that you will still find this piece useful.&lt;/p&gt;


 

&lt;h4&gt; What exactly is Vue.js? &lt;/h4&gt;

&lt;p&gt;For the sake of newbies, Vue.js is a JavaScript framework just like React and Angular. It focuses on the view layer (what the users of your application can see and interact with). Hence, it can be used to create powerful user interfaces. &lt;/p&gt;

&lt;p&gt;One of the most exciting things about this JavaScript framework is that it is very easy to learn and get started with compared to Angular or React. So within a couple of hours or days of learning Vue, you can start to create amazing web apps by just dropping the Vue.js cdn on your application. &lt;/p&gt;

&lt;p&gt;Anyways, without wasting much time, let's dive into the things that can make you a better Vue.js developer. 🤩&lt;/p&gt;

&lt;p&gt;1 &lt;b&gt;Let the documentation be your friend. READ IT!&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://vuejs.org/v2/guide/" rel="noopener noreferrer"&gt; Vue.js documentation&lt;/a&gt; is one of the best documentations you can ever come across. It's nicely written, well explained and has lots of examples.&lt;/p&gt;

&lt;p&gt;You can literally learn any Vue concept by just reading through the documentation. While building the e-commerce app, I always referred back to the documentation whenever I got stuck.&lt;/p&gt;

&lt;p&gt;So in addition to the tutorial you may have paid for, do well to regularly check out the docs.&lt;/p&gt;

&lt;p&gt;2 &lt;b&gt;Build projects&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;This tip can not be over emphasized.You need to start applying your knowledge of Vue to build projects. Begin with the Vue cdn. Don't wait till you begin to use the cli. &lt;b&gt; You may not appreciate the cli and maximize its benefits unless you have built something with the cdn. &lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Your first Vue app, doesn't have to be awesome. But as you progress in your learning path, you will naturally begin to build awesome Vue apps 🌟🌟&lt;/p&gt;

&lt;p&gt;3 &lt;b&gt;&lt;a href="%20https://vuetifyjs.com/en/"&gt;&lt;br&gt;
 Learn Vuetify&lt;/a&gt; &lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Is Vue.js not enough? Of course it is enough, especially when combined with your knowledge of CSS or SASS or Bootstrap or Tailwind CSS.&lt;/p&gt;

&lt;p&gt;So why learn Vuetify?&lt;/p&gt;

&lt;p&gt;Vuetify is a material design UI library specifically suited for Vue applications. It has built-in components such as cards, skeleton loaders, dialog box, datatables, buttons, carousel and a bunch of cool UI components that help you to build beautiful Vue apps &lt;b&gt;faster. &lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The cool thing is that Vuetify is written in Vue.js which makes getting started with it very easy.&lt;/p&gt;

&lt;p&gt;4 &lt;a href="https://nuxtjs.org/guide/views/" rel="noopener noreferrer"&gt; &lt;b&gt;Learn Nuxt.js&lt;/b&gt; &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, you got that right! The learning never stops.&lt;/p&gt;

&lt;p&gt;If you are coming from a React background, Nuxt.js is to Vue.js what Next.js is to React.&lt;/p&gt;

&lt;p&gt;My favorite coding tutor, Max, tagged his &lt;a href="https://www.udemy.com/course/nuxtjs-vuejs-on-steroids/" rel="noopener noreferrer"&gt; Nuxt.js Udemy course&lt;/a&gt; as &lt;b&gt; Vue.js on steroids &lt;/b&gt;😃&lt;/p&gt;

&lt;p&gt;You think vue.js is easy to work with? Then try out Nuxt.js. Nuxt.js further simplifies the development process of making Vue applications while adding extra capabilities such as server side rendering which undoubtedly improves the SEO of vue.js applications.&lt;/p&gt;

&lt;p&gt;So after gaining a mastery of vue.js concepts, learn Nuxt.js.&lt;/p&gt;

&lt;p&gt;5 &lt;b&gt;Build projects&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Oops! We've said that before.🤔.&lt;/p&gt;

&lt;p&gt;Yes, it's intentional! I can't stress this enough. You have to keep using your knowledge of Vue.js to build innovative solutions and make our world a better place.&lt;/p&gt;

&lt;p&gt;By so doing, you will become a better Vue.js developer. &lt;/p&gt;

&lt;p&gt;THANK YOU ❤️.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How To Add Speech Functionality To Your App</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Thu, 23 Apr 2020 10:02:21 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/how-to-add-speech-functionality-to-your-app-3l1e</link>
      <guid>https://dev.to/timothyokooboh/how-to-add-speech-functionality-to-your-app-3l1e</guid>
      <description>&lt;p&gt;In this article, I will show you how to add speech functionality to your applications. &lt;/p&gt;

&lt;p&gt;I recently made a simple &lt;a href="https://timothyokooboh.github.io/dictionary/#/" rel="noopener noreferrer"&gt; dictionary app &lt;/a&gt; with vue.js using the owlbot-js API. so I needed users to listen to the correct pronunciation of the words. I used the technique am about to show you and it took less than a minute to add speech functionality to my dictionary app. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S: On my android phone, I sometimes experience some delay before the voice note begins. But on my laptop, there is never a delay.&lt;/em&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  So let's begin!
&lt;/h1&gt;

&lt;p&gt;I'm gonna embed a code pen.&lt;br&gt;
&lt;iframe height="600" src="https://codepen.io/timopharm/embed/NWGdgao?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;First, we initialize the built-in speech synthesis API&lt;/p&gt;

&lt;p&gt;&lt;em&gt;const speech = window.speechSynthesis;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then, we access the DOM to select the text we want to get spoken.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;const text = document.querySelector("#text"). innerHTML;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The speech synthesis API has a constructor called SpeechSynthesisUtterance. This constructor receives one argument which is the text we want to get spoken. In our code, this argument is the same as the &lt;em&gt;text&lt;/em&gt; variable we declared.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;const utterance = new SpeechSynthesisUtterance(text)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, we created a variable called &lt;em&gt;utterance&lt;/em&gt; and assigned it the &lt;em&gt;SpeechUtterance&lt;/em&gt; constructor&lt;/p&gt;

&lt;p&gt;function sayTheWords(){&lt;br&gt;
  speech.speak(utterance);&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;Finally, when our button is clicked, we call the built-in &lt;em&gt;speak&lt;/em&gt; method on the speech synthesis API. The built-in &lt;em&gt;speak&lt;/em&gt; method receives one argument, which is the &lt;em&gt;utterance&lt;/em&gt; variable we declared.&lt;/p&gt;

&lt;h1&gt;
  
  
  So that's how you can add speech functionality to your app.
&lt;/h1&gt;

&lt;p&gt;You can think of several use cases where this functionality may be useful in your app. For instance, apart from displaying flash messages when a user creates, edits, or deletes a post, you could also send a voice message. &lt;/p&gt;

&lt;p&gt;To learn more about the speech synthesis API, you can check out this &lt;a href="https://www.youtube.com/watch?v=ZORXxxP49G8&amp;amp;t=184s" rel="noopener noreferrer"&gt; video by Brad Traversy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;He went further to explain how you could select the particular voice, pitch, and even the rate at which the voice note is spoken.&lt;/p&gt;

&lt;h1&gt;
  
  
  Thanks for reading.
&lt;/h1&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Simple Dynamic Quiz With Vue js</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Tue, 11 Feb 2020 09:37:32 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/simple-dynamic-quiz-with-vue-js-21c9</link>
      <guid>https://dev.to/timothyokooboh/simple-dynamic-quiz-with-vue-js-21c9</guid>
      <description>&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/timopharm/embed/dyooqrp?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>quiz</category>
      <category>codepen</category>
    </item>
    <item>
      <title>Rendering lists with progress bar in Vue JS.</title>
      <dc:creator>timothyokooboh</dc:creator>
      <pubDate>Sun, 09 Feb 2020 08:33:54 +0000</pubDate>
      <link>https://dev.to/timothyokooboh/rendering-lists-with-progress-bar-in-vue-js-4ne9</link>
      <guid>https://dev.to/timothyokooboh/rendering-lists-with-progress-bar-in-vue-js-4ne9</guid>
      <description>&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/timopharm/embed/MWwYqoL?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>codepen</category>
    </item>
  </channel>
</rss>
