<?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: Bitovi</title>
    <description>The latest articles on DEV Community by Bitovi (@bitovi).</description>
    <link>https://dev.to/bitovi</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%2Forganization%2Fprofile_image%2F883%2F02c38e09-b8eb-4080-a504-616a211e6b0d.png</url>
      <title>DEV Community: Bitovi</title>
      <link>https://dev.to/bitovi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bitovi"/>
    <language>en</language>
    <item>
      <title>Customize Jira's Advanced Planning Tool for Multiple Teams &amp; Projects</title>
      <dc:creator>amycutlip</dc:creator>
      <pubDate>Tue, 10 Sep 2024 15:40:04 +0000</pubDate>
      <link>https://dev.to/bitovi/customize-jiras-advanced-planning-tool-for-multiple-teams-projects-3ma0</link>
      <guid>https://dev.to/bitovi/customize-jiras-advanced-planning-tool-for-multiple-teams-projects-3ma0</guid>
      <description>&lt;p&gt;&lt;a href="https://www.atlassian.com/software/jira/guides/advanced-roadmaps/overview#what-is-advanced-planning" rel="noopener noreferrer"&gt;Jira’s Advanced Planning&lt;/a&gt; tool (the artist formerly known as Advanced Roadmaps) allows users to manage work across multiple projects, products, and teams. However, if you try to use Advanced Planning at scale, it is &lt;strong&gt;impossible&lt;/strong&gt; to set up plans that give each organizational unit what it &lt;strong&gt;needs&lt;/strong&gt;—a plan that shows their work and how it relates to other teams' work.&lt;/p&gt;

&lt;p&gt;We’ve created &lt;a href="https://github.com/bitovi/jira-plan-weaver-automations" rel="noopener noreferrer"&gt;PlanWeaver&lt;/a&gt;, a handful of open source Jira automations that give projects, products, and teams the ability to separate and report on the work of each unit or team involved in their program.&lt;/p&gt;

&lt;p&gt;In this article, you’ll learn why PlanWeaver is necessary for managing advanced plans at scale and how to implement the automations that make reporting on programs easier and more intuitive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is PlanWeaver needed?
&lt;/h2&gt;

&lt;p&gt;In most large organizations, multiple projects, products, and teams coordinate in various ways. In this article, we’ll use a fictional restaurant technology company called FastCo to illustrate how PlanWeaver can improve clarity within an organization.&lt;/p&gt;

&lt;p&gt;In our example, FastCo has multiple products serviced by multiple teams:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwg3i22j08hwoz9ygbzdl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwg3i22j08hwoz9ygbzdl.png" alt="Teams and Products" width="751" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;FastCo’s products and teams need to support multiple projects, programs, and initiatives that can vary in size and complexity. FastCo has multiple simultaneous implementation programs: Good Burger and Sunny Sushi. Each program contains initiatives that need to be completed by various teams:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68d7ydij3xcqghqgy025.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68d7ydij3xcqghqgy025.png" alt="Teams and Programs" width="754" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Out of the box, Advanced Planning doesn’t provide an easy way to visualize all projects on a &lt;strong&gt;team&lt;/strong&gt; or &lt;strong&gt;program&lt;/strong&gt; level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Team Level
&lt;/h3&gt;

&lt;p&gt;A team wants to see all the projects they are involved in and the other teams in those projects (so dependencies can be mapped).&lt;/p&gt;

&lt;p&gt;The image below shows all the initiatives that the &lt;code&gt;Order&lt;/code&gt; team is involved in, as well as the work of other teams in those initiatives.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv34tieq2gdkfu9okecuu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv34tieq2gdkfu9okecuu.png" alt="Order View" width="800" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Program Level
&lt;/h3&gt;

&lt;p&gt;A program wants to see all work within the program, across all of the program's initiatives. The image below shows Sunny Sushi’s work plan; a view not easily available out of box.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrfe9e03vhrfsvx0dc67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frrfe9e03vhrfsvx0dc67.png" alt="Sunny Sushi View" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The PlanWeaver automations simplify the creation of complex plans by tagging issues. These tags allow you to build the plans as shown above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Program-level views with Parent Tags
&lt;/h2&gt;

&lt;p&gt;Enter Parent and Child Tags. The PlanWeaver automations add two fields to issues that are Epic or higher in the issue hierarchy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Parent Tags&lt;/code&gt; - The project key of all parent issues of the current issue&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Child Tags&lt;/code&gt; - The project key of all children of the current issue (and the project key of epic siblings)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see how PlanWeaver’s tags work individually to create useful plans.&lt;/p&gt;

&lt;h3&gt;
  
  
  Program-level views with Parent Tags
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Parent Tags&lt;/code&gt; help you build a program or project-level view. Every child of a higher-order issue is tagged with that issue’s project key.&lt;/p&gt;

&lt;p&gt;In the image below, Parent Tags allow users to see all of the work related to the Good Burger program. We can see multiple initiatives and their related epics across various teams. Simply querying by the parent tag allows a user to see an organized view of the work planned for the program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu462cyuarlo3hse0qg8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu462cyuarlo3hse0qg8n.png" alt="Parent Tag Roadmap" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the following filter for this Advanced Timeline Plan view:&lt;/p&gt;

&lt;p&gt;"Parent Tags[Labels]" = GOODBURGER or project = "Good Burger"&lt;/p&gt;

&lt;p&gt;There are two automation files for Parent Tags: one that updates Parent Tags when an issue is changed, and one that populates the Parent Tags in parent issues.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="https://www.bitovi.com/hubfs/Jira%20Parent%20Child%20Automation%20Blog/jira-plan-weaver-automations-main.zip" rel="noopener noreferrer"&gt;⬇️ Download JSON file&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Team views with Child Tags
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Child Tags&lt;/code&gt; help you build a view of not only a team’s work but also related work from other projects. Child tags improve the Advanced Plans view when a single team has work across multiple programs or projects and needs a way to view it all along with the dependencies.&lt;/p&gt;

&lt;p&gt;Below is a view for the Order team, displaying not only the work for the team across multiple initiatives but also the work from other teams that may have dependencies with the Order team’s work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7r4aq0834jdfnm4jrz3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7r4aq0834jdfnm4jrz3p.png" alt="Child Example Roadmap" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the following filter for this Advanced Timeline Plan view:&lt;/p&gt;

&lt;p&gt;"Child Tags[Labels]" = ORDER&lt;/p&gt;

&lt;p&gt;There are three JSON files for Child Tags: one to update Child Tags when a parent issue is changed, another to update Child Tags when an issue is moved, and a final automation to update a parent issue's tags when Child Tags change.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;&lt;a href="https://www.bitovi.com/hubfs/Jira%20Parent%20Child%20Automation%20Blog/jira-plan-weaver-automations-main.zip" rel="noopener noreferrer"&gt;⬇️ Download JSON file&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Out of the box, it's a challenge to use Jira’s Advanced Planning at an enterprise scale. With our open source PlanWeaver add-on, Advanced Planning becomes more useful for teams to view their work across programs. Adding Epic-level tags enhances reporting and allows program managers and teams to view their work—and how their work impacts other teams—more intuitively.&lt;/p&gt;

&lt;p&gt;At Bitovi, we focus on helping our clients make the right decisions for their products and company. Developing new ways to view work, like our PlanWeaver automation, is another way we’re working to perfect product delivery. We’ll have another post soon walking through how to import and use the PlanWeaver automations. In the meantime, be sure to join our &lt;a href="https://discord.gg/J7ejFsZnJ4" rel="noopener noreferrer"&gt;Community Discord&lt;/a&gt; for support and inspiration. Happy planning!&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>product</category>
      <category>agile</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Protect Your Business from IT Disasters: Lessons from the CrowdStrike Outage</title>
      <dc:creator>amycutlip</dc:creator>
      <pubDate>Thu, 25 Jul 2024 19:32:26 +0000</pubDate>
      <link>https://dev.to/bitovi/protect-your-business-from-it-disasters-lessons-from-the-crowdstrike-outage-12hm</link>
      <guid>https://dev.to/bitovi/protect-your-business-from-it-disasters-lessons-from-the-crowdstrike-outage-12hm</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89flkq7r5b450q93i0pj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89flkq7r5b450q93i0pj.png" alt="Image description" width="800" height="418"&gt;&lt;/a&gt;&lt;br&gt;
Businesses heavily rely on IT infrastructure for smooth operations and security, but what happens when that infrastructure breaks? Thousands of companies were blindsided by a sudden CrowdStrike outage on Friday, July 19th, leading to a projected cost of &lt;a href="https://www.cnn.com/2024/07/21/business/crowdstrike-outage-cost/index.html" rel="noopener noreferrer"&gt;$1 Billion&lt;/a&gt;. With an estimated 8.5 million devices impacted by the outage, over 5,000 canceled flights, and hundreds of hospital computer systems offline, you’re probably wondering: &lt;em&gt;What can I do to prevent a CrowdStrike-level business disruption?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this blog, you’ll learn the business impacts of IT disasters, how to prevent them, and the steps you can take today to protect your organization from similar threats.&lt;/p&gt;

&lt;h3&gt;
  
  
  Up first: Who is Bitovi?
&lt;/h3&gt;

&lt;p&gt;Bitovi is a digital product consultancy dedicated to perfecting product delivery. We’ve provided &lt;a href="https://www.bitovi.com/services/quality-engineering-consulting" rel="noopener noreferrer"&gt;Quality Engineering Consulting&lt;/a&gt; to businesses of all sizes—from lean startups to Fortune 500 enterprises. We write about improving software engineering and delivery practices.&lt;/p&gt;

&lt;p&gt;Learn more about Bitovi’s &lt;a href="https://www.bitovi.com/digital-consulting-services" rel="noopener noreferrer"&gt;digital consulting services&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Business disruptions and financial losses from IT outages
&lt;/h2&gt;

&lt;p&gt;The CrowdStrike outage serves as a wake-up call to businesses about the severe disruptions that IT failures can cause. Financial losses, operational disruptions, and reputation damage—&lt;strong&gt;when critical IT infrastructure fails, the ripple effects can be vast and costly.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Financial losses from IT disasters like the CrowdStrike outage
&lt;/h3&gt;

&lt;p&gt;During the CrowdStrike outage, businesses faced immediate operational challenges. With over 8.5 million devices affected globally, revenue loss during the downtime period was a severe blow to many companies' financial health.&lt;/p&gt;

&lt;p&gt;The estimated $1 billion cost reflects not only lost productivity but also the emergency IT remediation efforts required to address the outage. Businesses had to bear the costs associated with restoring operations, including overtime payments to IT staff and, in some cases, hiring specialized consultants.&lt;/p&gt;

&lt;p&gt;The financial impacts of IT disruptions are overwhelming, but there is a way forward. Investing in a robust Quality Engineering practice allows organizations to prevent significant disruptions and address them quickly if they do occur.&lt;/p&gt;

&lt;p&gt;“In light of the CrowdStrike outage, investing in Quality Engineering is essential. It helps prevent disruptions and ensures quick recovery, minimizing financial losses and protecting business reputation,” says Bitovi’s Director of &lt;a href="https://www.bitovi.com/services/quality-engineering-consulting" rel="noopener noreferrer"&gt;Quality Engineering Consulting&lt;/a&gt;, Denison Luz.&lt;/p&gt;

&lt;h3&gt;
  
  
  Operational disruptions caused by IT outages
&lt;/h3&gt;

&lt;p&gt;On a human level, the operational disruptions were more devastating than the financial impacts. Industries that depend on real-time data and continuous operations, like airlines, healthcare, and banking, were particularly hard hit. The outage led to the cancellation of over 5,000 flights, causing widespread travel chaos and leaving passengers stranded in airports worldwide. Hospitals struggled to maintain patient care as critical computer systems went offline, forcing staff to revert to manual processes prone to errors and inefficiencies. The impact on patient safety and care quality was a stark reminder of how dependent modern healthcare systems are on reliable IT infrastructure.&lt;/p&gt;

&lt;p&gt;[nurse quote, verifying with sources]&lt;/p&gt;

&lt;p&gt;These disruptions underscored the need for robust and resilient IT systems that can withstand unexpected failures. Quality Engineering establishes safeguards like regression testing, which ensures new updates are compatible with older systems, keeping systems online and providing critical services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reputation damage caused by IT infrastructure failures
&lt;/h3&gt;

&lt;p&gt;Reputation damage is another critical aspect that businesses must consider. For businesses, trust is paramount. An outage that compromises security or disrupts services can erode customer confidence and damage a company’s reputation. The long-term impact on customer trust can be even more damaging than the immediate financial losses. Companies that experience significant outages often face backlash from customers and negative media coverage, which can take years to recover from.&lt;/p&gt;

&lt;p&gt;The CrowdStrike outage is a potent reminder that &lt;strong&gt;IT resilience is not just a technical issue but a critical business priority&lt;/strong&gt;. Ensuring that your IT systems are robust and capable of withstanding failures can protect your business from severe financial losses and operational disruptions. It is essential for business leaders to prioritize Quality Engineering and proactive measures to safeguard their organizations against similar threats. Not sure where to start? It’s not too late to preserve your reputation for quality—Bitovi’s &lt;a href="https://www.bitovi.com/digital-consulting-services" rel="noopener noreferrer"&gt;Quality Engineering Consultants&lt;/a&gt; are available to help enhance your testing practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Quality Engineering to prevent IT outages
&lt;/h2&gt;

&lt;p&gt;People sleeping in airports, plunging stock prices, healthcare disruptions—the CrowdStrike outage made waves beyond the tech industry, affecting millions of businesses and individuals worldwide.&lt;/p&gt;

&lt;p&gt;Establishing robust IT infrastructure and proactive measures to prevent such disasters has never been more important. Businesses must recognize the vulnerabilities in their systems and the need for continuous monitoring and quality engineering to ensure resilience.&lt;/p&gt;

&lt;p&gt;Investing in advanced Quality Engineering practices and implementing regular quality checks can help in identifying potential points of failure before they lead to significant disruptions. Moreover, having a well-defined incident response plan can mitigate the impact when an outage does occur. Proactive measures like stress testing systems and regular drills can prepare businesses to handle unexpected IT failures more effectively, minimizing downtime and associated costs.&lt;/p&gt;

&lt;p&gt;Bitovi can help establish the safeguards to protect your business from IT disruptions. Contact our &lt;a href="https://www.bitovi.com/services/quality-engineering-consulting" rel="noopener noreferrer"&gt;Quality Engineering Consulting&lt;/a&gt; experts for a free consultation.&lt;/p&gt;

</description>
      <category>qa</category>
      <category>news</category>
      <category>qualityengineering</category>
    </item>
    <item>
      <title>Hatchify: The Fastest Way to Build JSON: APIs</title>
      <dc:creator>Heather Stevens</dc:creator>
      <pubDate>Fri, 22 Mar 2024 14:58:44 +0000</pubDate>
      <link>https://dev.to/bitovi/hatchify-the-fastest-way-to-build-json-apis-ih3</link>
      <guid>https://dev.to/bitovi/hatchify-the-fastest-way-to-build-json-apis-ih3</guid>
      <description>&lt;p&gt;Last week, &lt;a href="https://bitovi.com/blog/introducing-hatchify-low-code-libraries-for-react-node-and-sequelize"&gt;Bitovi Hatchify&lt;/a&gt; officially left the nest! Hatchify is a suite of low-code libraries that provides a powerful scaffold to build CRUD-heavy applications, eliminate boilerplate, and enable your team to focus on domain-specific functionality from day one. Hatchify empowers you to build admin views, dashboards, and B2B apps faster, all while retaining uncompromising flexibility.&lt;/p&gt;

&lt;p&gt;One of Hatchify’s long-term objectives is to help developers move faster across all layers of the web stack. In the initial release, we’re most proud of our backend feature set that helps get CRUD API development out of the way early. We built the fastest way to get a high-quality &lt;a href="https://jsonapi.org/"&gt;JSON: API&lt;/a&gt; implementation packed with features like &lt;a href="https://github.com/bitovi/hatchify/blob/main/docs/jsonapi/reading/filtering/README.md"&gt;advanced filtering capabilities&lt;/a&gt;, &lt;a href="https://github.com/bitovi/hatchify/tree/main/docs/jsonapi/reading/relationships"&gt;related data queries&lt;/a&gt;, and &lt;a href="https://github.com/bitovi/hatchify/blob/main/docs/jsonapi/reading/sparse-fields/README.md"&gt;specified response fields&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  APIs, Accelerated
&lt;/h2&gt;

&lt;p&gt;A high-quality CRUD API can require typing up a tedious amount of boilerplate code. The API standards, the ORM, the basic route handlers — there’s lots to do before you even have a running app to iterate on. Although code generation tools can help you get a leg up on the initial effort, they can add friction should you eventually need to modify all the generated output. By dynamically defining the backend at runtime, based on your data model, Hatchify solves the same problems as code generation without the friction of schema updates. Hatchify applications adapt to data model &amp;amp; library updates without having to revise all of the generated files.&lt;/p&gt;

&lt;p&gt;In addition to saving you time on boilerplate, the API provided by Hatchify fully implements the &lt;a href="https://jsonapi.org/"&gt;JSON: API&lt;/a&gt; specification, which stipulates solid standards to define the peculiarities of CRUD REST APIs. Get back all the time spent bike-shedding how to implement standard API features like filtering, pagination, including related data, etc. &lt;a href="https://jsonapi.org/"&gt;JSON: API&lt;/a&gt; offers consistent practices for frontend and backend developers to agree on how resources are fetched and returned. Since Hatchify provides the core of your API for you, you can count on it’s standardized functionality to give your API a consistent start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Modeling
&lt;/h2&gt;

&lt;p&gt;To save all of this time, Hatchify depends on descriptions of the data it will be serving. This data model is written in a simple TypeScript format we call Schemas. Using those descriptions, Hatchify produces a starter application that your team can begin iterating on immediately. Schemas are consumed by the Hatchify ORM, HTTP router, and frontend elements, to configure themselves appropriately for the different resources held in your database.&lt;/p&gt;

&lt;p&gt;For example, two schemas for a simple to-do list application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkqodwspy5se6khvjhpm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkqodwspy5se6khvjhpm.png" alt="Image description" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From that business context, Hatchify can provide a fully functional API, a basic UI, and a React-hook interface to trivialize API access from React-based apps. The API features are showcased in the example below:&lt;/p&gt;

&lt;p&gt;We can create an API for two different resources with the ability to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do basic CRUD&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bitovi/hatchify/tree/main/docs/jsonapi/reading/filtering"&gt;Use advanced filters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Query-related data in a single request

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jsonapi.org/format/#document-compound-documents"&gt;Including normalization of related data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jsonapi.org/format/#fetching-sparse-fieldsets"&gt;Query only for specified fields&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Use page or offset/limit-based &lt;a href="https://github.com/bitovi/hatchify/tree/main/docs/jsonapi/reading/paginating"&gt;pagination&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a complete devo of the above capabilities, head to our demo on &lt;a href="https://stackblitz.com/edit/bitovi-hatchify-px3uyd?file=demo.ts"&gt;StackBlitz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that you have the foundational CRUD structure managed, you can seamlessly transition to expanding your API capabilities with any custom endpoints you might need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flexibility First
&lt;/h2&gt;

&lt;p&gt;If eventually you find your API requires functionality beyond what Hatchify can provide, our modular approach to building the framework allows you to continue using whatever portions make sense for your uses case. The ORM, HTTP router, request parsing/serialization can all be used independently. We designed Hatchify to provide enough functionality for most apps while providing an easy transition for those who eventually want more control.&lt;/p&gt;

&lt;p&gt;Bitovi is committed to keeping Hatchify free and open-source. We believe good software should be accessible to everyone, and we’ll never charge you to use Hatchify.&lt;/p&gt;

&lt;p&gt;Our team works to support Hatchify in all modern JS/TS web applications environments, and integrate with all application (meta)frameworks. We are currently working on integration guides for Next.js, Remix and Astro. Our goal is to maintain extensive guides on how we at Bitovi (and the community) have adapted Hatchify for different usages. If you are interested in how Hatchify might work with your existing or prospective web technology stack, say “hi!” in our Discord and we can investigate that together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leaving The Nest
&lt;/h2&gt;

&lt;p&gt;Hatchify is taking flight and we’re excited for devs to get back all the time they were going to spend writing CRUD API boilerplate. Our current roadmap includes:&lt;/p&gt;

&lt;p&gt;Schema-driven form builder to easily create and edit data&lt;br&gt;
Authorization support&lt;br&gt;
Data migrations&lt;br&gt;
More documentation improvements &amp;amp; integration guides&lt;br&gt;
If there’s something you’d like to see, let us know on Github!&lt;/p&gt;

&lt;p&gt;We want to make every dev more efficient - writing schemas in the morning, and building the important parts of their app by lunch. We hope that you’ll be one of the first. Find out more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read our &lt;a href="https://github.com/bitovi/hatchify/blob/main/README.md"&gt;Getting Started Guide&lt;/a&gt; and &lt;a href="https://github.com/bitovi/hatchify/blob/main/docs/api-documentation.md"&gt;API Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Get help and support on &lt;a href="https://discord.gg/JZcxKEMa5e"&gt;Bitovi’s Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow Bitovi on &lt;a href="https://www.linkedin.com/company/3153182"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://twitter.com/bitovi"&gt;Twitter&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks!&lt;/p&gt;

&lt;p&gt;🐣 Nils &amp;amp; The Hatchify Team&lt;/p&gt;

</description>
      <category>api</category>
      <category>opensource</category>
      <category>react</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Introducing Hatchify: Low-code libraries for React, Node, and Sequelize</title>
      <dc:creator>Heather Stevens</dc:creator>
      <pubDate>Wed, 13 Mar 2024 18:50:01 +0000</pubDate>
      <link>https://dev.to/bitovi/introducing-hatchify-low-code-libraries-for-react-node-and-sequelize-4i9i</link>
      <guid>https://dev.to/bitovi/introducing-hatchify-low-code-libraries-for-react-node-and-sequelize-4i9i</guid>
      <description>&lt;p&gt;We are pleased to announce Hatchify - a tool that helps developers build React, NodeJS, and Sequelize apps swiftly. Hatchify provides the speed of a low-code development while enabling complete customization in the patterns familiar to React and Node developers.&lt;/p&gt;

&lt;p&gt;If you are starting a new project, check out our &lt;a href="https://github.com/bitovi/hatchify/blob/main/README.md"&gt;Getting Started Guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Hatchify and what does it do?
&lt;/h2&gt;

&lt;p&gt;Hatchify is a collection of JavaScript libraries for the frontend and backend that takes a data schema and builds commonly needed functionality (like services and grids) while allowing customization later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa6wiar1zkqxicym6qsq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa6wiar1zkqxicym6qsq.png" alt="Image description" width="800" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To use Hatchify, define your app's data schemas as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Schemas = {
  Todo: {
    attributes: {
      name: string({ required: true }),
      dueDate: dateonly(),
      ...
    },
    relationships: {
      user: belongsTo("User"),
    },
  }
  User: {
    attributes: {
      name: string({ required: true }),
    },
    relationships: {
      todos: hasMany("Todo"),
    },
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a schema, Hatchify creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sequelize object-relational-mapping (ORM) classes&lt;/li&gt;
&lt;li&gt;Flexible REST services&lt;/li&gt;
&lt;li&gt;Frontend models&lt;/li&gt;
&lt;li&gt;Frontend components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next sections detail how you’d use these parts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sequelize ORM classes
&lt;/h3&gt;

&lt;p&gt;hatchifyKoa(schemas).orm.models provides Sequelize classes you can use to query and manipulate the database directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const hatchedKoa = hatchifyKoa(schemas);
const Todo = hatchedKoa.orm.models.Todo;

await Todo.getList({where: {name: "Learn Hatchify"}})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Access to the underlying ORM allows you to weave in custom behavior such as advanced validation, while still keeping the benefits of the rest of the toolchain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexible REST services
&lt;/h3&gt;

&lt;p&gt;hatchifyKoa(schemas).middleware provides a flexible and expressive REST API, letting you &lt;a href="https://github.com/bitovi/hatchify/blob/main/docs/jsonapi/reading/filtering/README.md"&gt;filter&lt;/a&gt;, &lt;a href="https://github.com/bitovi/hatchify/blob/main/docs/jsonapi/reading/paginating/README.md#learn-how-to-paginate-data"&gt;paginate&lt;/a&gt;, &lt;a href="https://github.com/bitovi/hatchify/blob/main/docs/jsonapi/reading/sorting/README.md"&gt;sort&lt;/a&gt;, &lt;a href="https://github.com/bitovi/hatchify/blob/main/docs/jsonapi/reading/sparse-fields/README.md"&gt;specify specific fields&lt;/a&gt;, and even &lt;a href="https://github.com/bitovi/hatchify/blob/main/docs/jsonapi/reading/relationships/README.md"&gt;include data across tables&lt;/a&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/todos
  ?include=user
  &amp;amp;fields[User]=name
  &amp;amp;filter[user.name][$ilike]=%Joe%
  &amp;amp;page[limit]=10
  &amp;amp;page[offset]=0
  &amp;amp;sort=dueDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Frontend model layer
&lt;/h3&gt;

&lt;p&gt;hatchifyReact(schema).model creates React data models and hooks, with full TypeScript support. The React data model can take advantage of filtering, relationships, and pagination - everything the service layer provides. The hooks also update automatically when there are changes (stale-while-revalidate for the win).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [joesTodos, joesTodosState] = hatchedReact.model.Todo.useAll({
  include: ["user"],
  fields: { "User": ["name"] },
  filter: { "user.name": { $ilike: "Joe%" } },
  page: { limit: 10, offset: 0 },
  sort: ['dueDate'],
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;hatchifyReact(schema).components includes a data grid that supports filtering, pagination, and sorting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7n6mdu0030d5xy9p7lxq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7n6mdu0030d5xy9p7lxq.gif" alt="Image description" width="770" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Hatchify team's next major step is adding components to create and edit data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem is Hatchify solving?
&lt;/h2&gt;

&lt;p&gt;Hatchify is trying to fill a gap between low-code solutions and CRUD generators.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtg960gue4pi7426a154.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtg960gue4pi7426a154.png" alt="breakdown of code levels" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The set-up of a new project can be complex and cumbersome. This gets in the way of agile development, where there is working software to review, adjust, and iterate from.&lt;/p&gt;

&lt;p&gt;While there are many code generators and templates to bootstrap a new project, once you start customizing the app or updating the data model, you’re on your own. You have to make those customizations manually, often in multiple different places. You can’t keep experiencing the benefits of the code generator.&lt;/p&gt;

&lt;p&gt;Therefore, Hatchify is trying to solve 3 problems simultaneously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable rapid creation of prototype applications&lt;/li&gt;
&lt;li&gt;Enable complete customization of the application&lt;/li&gt;
&lt;li&gt;Continually providing value while customizing or adding new features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means Hatchify is not a code generator or a limiting low-code tool. Instead, it’s a bunch of libraries that you can use whole or in part to match your needs.&lt;/p&gt;

&lt;p&gt;At the start of the project, a simple schema will provide you with a working app. An app where you can have conversations with the customer; and designers and developers can begin to iterate.&lt;/p&gt;

&lt;p&gt;When you make changes, you can rewrite just the parts you need to change. The rest of the app can still be updated like a low-code tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is it for?
&lt;/h2&gt;

&lt;p&gt;Hatchify is for products that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have CRUD-type behavior&lt;/li&gt;
&lt;li&gt;Anticipate a lot of customization&lt;/li&gt;
&lt;li&gt;Are built on NodeJS, REST, and React&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hatchify can’t fully compete with a low-code tool yet. You’ll have to build functionality like forms and authorization yourself. But, Hatchify provides a lot of value connecting (with strong TypeScript support) the frontend data layer all the way to the backend model layer and back:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmkmrp0hr67wvy0c0bu02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmkmrp0hr67wvy0c0bu02.png" alt="Image description" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is using it?
&lt;/h2&gt;

&lt;p&gt;We’re using Hatchify at &lt;a href="https://www.bitovi.com/"&gt;Bitovi&lt;/a&gt; for all new application development (where Node and React are the stack). We partnered with &lt;a href="https://kleartrust.com/"&gt;KlearTrust&lt;/a&gt;, a leader in Health IT, to develop Hatchify.&lt;/p&gt;

&lt;p&gt;KlearTrust had a good understanding of their data model and needed to quickly validate their designs, while simultaneously building a production application. You can see the sortable and filterable Hatchify DataGrid below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffehlvk5ek559mhwjaynt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffehlvk5ek559mhwjaynt.png" alt="Image description" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using Hatchify, KlearTrust was able to accelerate its development of the full application, providing a straightforward UI (built atop the DataGrid) to manage a reasonably complex data model. You can see Andy Schriever, Senior Vice President of KlearTrust, share his thoughts on using Hatchify.&lt;/p&gt;

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

&lt;p&gt;We’re hopeful you will check out Hatchify and find it as useful as KlearTrust has!&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;Our goal is to make Hatchify the swiftest way to build custom CRUD apps (or the swiftest way to build the CRUD elements of larger apps). Pending &lt;a href="https://github.com/bitovi/hatchify/issues"&gt;community feedback&lt;/a&gt;, we plan to add the following features immediately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forms to create and edit data&lt;/li&gt;
&lt;li&gt;CRUD authorization support&lt;/li&gt;
&lt;li&gt;Data migrations&lt;/li&gt;
&lt;li&gt;Continued documentation improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there’s something you’d like to see, let us know on &lt;a href="https://github.com/bitovi/hatchify"&gt;Github&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;To get started on Hatchify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read our &lt;a href="https://github.com/bitovi/hatchify/blob/main/README.md"&gt;Getting Started Guide&lt;/a&gt; and &lt;a href="https://github.com/bitovi/hatchify/blob/main/docs/api-documentation.md"&gt;API Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Get help and support on &lt;a href="https://discord.gg/JZcxKEMa5e"&gt;Bitovi’s Discord&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Follow Bitovi on &lt;a href="https://www.linkedin.com/company/3153182"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://twitter.com/bitovi"&gt;X&lt;/a&gt; for updates as they happen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks! &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hatchify Team&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>typescript</category>
      <category>sql</category>
      <category>node</category>
    </item>
    <item>
      <title>Collection of Vue Macros in Vue.js 3.3</title>
      <dc:creator>Eduard Krivanek</dc:creator>
      <pubDate>Sun, 28 May 2023 11:06:16 +0000</pubDate>
      <link>https://dev.to/bitovi/collection-of-vue-macros-in-vuejs-33-i51</link>
      <guid>https://dev.to/bitovi/collection-of-vue-macros-in-vuejs-33-i51</guid>
      <description>&lt;p&gt;Many developers (myself included) were excited when &lt;a href="https://blog.vuejs.org/posts/vue-3-3" rel="noopener noreferrer"&gt;Vue.js version 3.3&lt;/a&gt; introduced several functionalities from &lt;a href="https://vue-macros.sxzz.moe/" rel="noopener noreferrer"&gt;Vue Macros&lt;/a&gt;, the collection of proposed additions to Vue.js that extend its basic functionalities with syntactic sugar.&lt;/p&gt;

&lt;p&gt;In this post, you will learn about Vue Macros that became a part of Vue version 3.3 and how you can use them if you are not yet on version 3.3.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Vue Macros?
&lt;/h2&gt;

&lt;p&gt;Let's go straight to the source! The official website claims the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Vue Macros is a library that implements proposals or ideas that have not been officially implemented by Vue. That means it will explore and extend more features and syntax sugar to Vue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking at its &lt;a href="https://github.com/sxzz/vue-macros" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; repo, the library is well maintained. Moreover, Vue Macros supports Vue from version 2.7. To &lt;a href="https://vue-macros.sxzz.moe/guide/bundler-integration.html" rel="noopener noreferrer"&gt;install Vue Macros&lt;/a&gt;, you need to run &lt;code&gt;npm i -D unplugin-vue-macros&lt;/code&gt;, configure &lt;code&gt;vite.config.ts&lt;/code&gt;, and the &lt;code&gt;tsconfig.json&lt;/code&gt; as is installation suggests to start using them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Which Macros do I want to use&lt;/em&gt;, you ask? Let’s look into Macros introduced as part of Vue version 3.3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Macro defineModels
&lt;/h3&gt;

&lt;p&gt;Prior to v3.3, when it came to component two-way  binding with &lt;code&gt;v-model&lt;/code&gt;, we had to implement &lt;code&gt;props&lt;/code&gt; and &lt;code&gt;emits&lt;/code&gt; in the child component to receive or notify the parent component about a data change. You usually end up with the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;    // MySearch.vue

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
          &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"data in store.getLoadedElements"&lt;/span&gt;
          &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"data.title"&lt;/span&gt;
          &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"() =&amp;gt; onInput(data)"&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// some additional code&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&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;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;emits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineEmits&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// some additional code&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://vue-macros.sxzz.moe/macros/define-models.html" rel="noopener noreferrer"&gt;defineModels&lt;/a&gt; macro is a syntactic sugar by which you can avoid implementing two-way binding for using &lt;a href="https://vuejs.org/guide/components/v-model.html" rel="noopener noreferrer"&gt;v-model&lt;/a&gt; on the component level instead of the default Vue.js implementation. You can achieve the above logic with the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;    // MySearch.vue

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
         &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"data in store.getLoadedElements"&lt;/span&gt;
         &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"data.title"&lt;/span&gt;
         &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"modelValue = data"&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// some additional code&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;modelValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineModels&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// some additional code&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue.js 3.3 recently received the &lt;code&gt;defineModels&lt;/code&gt; enhancement for two-way binding under the name &lt;a href="https://blog.vuejs.org/posts/vue-3-3#definemodel" rel="noopener noreferrer"&gt;defineModel&lt;/a&gt;, which has the exact same functionality.&lt;/p&gt;

&lt;p&gt;You will find more information in our blog post: &lt;a href="https://www.bitovi.com/blog/new-in-vue-3.3-two-way-binding-with-definemodel-macro" rel="noopener noreferrer"&gt;New in Vue.js 3.3: Two-Way Binding With defineModel Macro&lt;/a&gt;. However, opting for the &lt;code&gt;defineModel&lt;/code&gt; functionality in Vue.js 3.3, as it is still an experimental feature, you have to modify your &lt;code&gt;vite.config.ts&lt;/code&gt; in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nf"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;defineModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="c1"&gt;// ^^ enables the feature&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Macro definePropsRefs
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.vuejs.org/posts/vue-3-3#reactive-props-destructure" rel="noopener noreferrer"&gt;Reactive props destructuring&lt;/a&gt; was quite a requested feature from the Vue.js community. It’s safe to say the developer was excited about the feature released in Vue 3.3. However, the older Vue.js version still receives the following error message when trying to destructure props.&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%2Fcoz9tw7qxbf1d4itfdq0.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%2Fcoz9tw7qxbf1d4itfdq0.png" alt="macrodefineprops" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fortunately, the &lt;a href="https://vue-macros.sxzz.moe/macros/define-props-refs.html" rel="noopener noreferrer"&gt;macro definePropsRefs&lt;/a&gt; allows us property destructuring by writing the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;showModal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inputValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;definePropsRefs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;showModal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&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="na"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
      &lt;span class="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;Using Vue Macros are much better developer experience than destructuring properties before version 3.3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;showModal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inputValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toRefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;withDefaults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;defineProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;showModal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;required&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="na"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="p"&gt;}),&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="na"&gt;showModal&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="na"&gt;inputValue&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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to use &lt;code&gt;defineProps&lt;/code&gt; an experimental feature in Vue version 3.3, you have to opt-in with the following configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// vite.config.js&lt;/span&gt;
    &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nf"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;propsDestructure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="c1"&gt;// ^^ enables the feature&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Macro defineEmit
&lt;/h3&gt;

&lt;p&gt;Using &lt;code&gt;defineEmits&lt;/code&gt; wasn’t such a bad experience. You declared and used emits in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineEmits&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;a href="https://vue-macros.sxzz.moe/macros/define-emit.html" rel="noopener noreferrer"&gt;defineEmit&lt;/a&gt; from Vue Macros, you get the advantage of declaring individual emits in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// Declare emit&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineEmit&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="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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Infer emit name from variable name&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineEmit&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="c1"&gt;// Emit array of strings&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineEmit&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="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10&lt;/span&gt;&lt;span class="dl"&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="s1"&gt;test1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vue 3.3 brought a little bit of syntactic sugar, &lt;a href="https://blog.vuejs.org/posts/vue-3-3#more-ergonomic-defineemits" rel="noopener noreferrer"&gt;working with defineEmits&lt;/a&gt; in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineEmits&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fortunately, there is no opting-in for this feature, so you can use it right away!&lt;/p&gt;

&lt;h3&gt;
  
  
  Macro defineSlots
&lt;/h3&gt;

&lt;p&gt;When working with &lt;a href="https://vuejs.org/guide/components/slots.html#scoped-slots" rel="noopener noreferrer"&gt;scoped slots&lt;/a&gt; in Vue.js, one problem we faced was not knowing what properties were available on the parent component. Here is the following example before Vue version 3.3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;    &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;ChildComponent&amp;gt; template --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="na"&gt;:text=&lt;/span&gt;&lt;span class="s"&gt;"greetingMessage"&lt;/span&gt; &lt;span class="na"&gt;:count=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/slot&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    // ------------------------------------------

    &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;ParentComponent&amp;gt; template --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;v-slot=&lt;/span&gt;&lt;span class="s"&gt;"slotProps"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      {{ slotProps.text }} {{ slotProps.count }}
    &lt;span class="nt"&gt;&amp;lt;/MyComponent&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A developer may access &lt;code&gt;slotProps.anything&lt;/code&gt; and receive an error only during the runtime.&lt;/p&gt;

&lt;p&gt;Vue.js 3.3 introduced &lt;code&gt;defineSlots&lt;/code&gt;, which use &lt;a href="https://blog.vuejs.org/posts/vue-3-3#typed-slots-with-defineslots" rel="noopener noreferrer"&gt;types slots&lt;/a&gt;, eliminating the parent component of accessing non-existing props from the child. Here is the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;    &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;ChildComponent&amp;gt; --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"item of items"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Name&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

        &lt;span class="c"&gt;&amp;lt;!-- default slot --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;slot&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"itemNameSlot"&lt;/span&gt; &lt;span class="na"&gt;:item-name=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/slot&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;item3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nx"&gt;defineSlots&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;itemNameSlot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;itemName&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="nx"&gt;any&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="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    // ----------------------------

    &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;ParentComponent&amp;gt; --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;Test&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#itemNameSlot&lt;/span&gt;&lt;span class="err"&gt;="&lt;/span&gt;{ itemName }"&amp;gt;
           &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;:href=&lt;/span&gt;&lt;span class="s"&gt;"`/someurl/$&lt;/span&gt;{itemName}`"&amp;gt; 
             &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;itemName&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; - click 
           &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;/Test&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you replace the &lt;code&gt;itemName&lt;/code&gt; with a different value in the &lt;code&gt;#itemNameSlot="{ itemName }"&lt;/code&gt; in the parent component, you will receive the following error:&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%2Fqzwfjoj8n1a16afh71ta.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%2Fqzwfjoj8n1a16afh71ta.png" alt="macrodefineslots" width="699" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fortunately, there is already a macro for the same functionality with the same name - &lt;a href="https://vue-macros.sxzz.moe/macros/define-slots.html" rel="noopener noreferrer"&gt;defineSlots&lt;/a&gt; from Vue Macros if you are not yet on version 3.3.&lt;/p&gt;

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

&lt;p&gt;Vue.js 3.3 brought new features that developers were waiting for. The community has already implemented most of these features in a package called &lt;a href="https://vue-macros.sxzz.moe/guide/getting-started.html" rel="noopener noreferrer"&gt;Vue Macros&lt;/a&gt;. It is a small but convenient collection of utils that can be used even on Vue version 2.7.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Vue.js Reactivity System: Ref, reactive, shallowRef, &amp; shallowReactive</title>
      <dc:creator>Eduard Krivanek</dc:creator>
      <pubDate>Thu, 18 May 2023 10:55:55 +0000</pubDate>
      <link>https://dev.to/bitovi/vuejs-reactivity-system-ref-reactive-shallowref-shallowreactive-oe7</link>
      <guid>https://dev.to/bitovi/vuejs-reactivity-system-ref-reactive-shallowref-shallowreactive-oe7</guid>
      <description>&lt;p&gt;Vue.js is a popular JavaScript framework that provides developers with various tools to create dynamic and reactive web applications.&lt;/p&gt;

&lt;p&gt;One of the key features of Vue is its reactivity system, which enables the framework to efficiently update the view when the state changes. In this blog post, you’ll learn the different types of reactive objects, such as &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt;, when to use which, and ones that you maybe haven’t heard of like &lt;code&gt;shallowRef&lt;/code&gt; and &lt;code&gt;shallowReactive&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Ref?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;ref&lt;/code&gt; function is used to create a reactive reference to a single value. This value can be a primitive type like a string or number or an object or array.&lt;/p&gt;

&lt;p&gt;To access the value of the ref function, you need to use the &lt;code&gt;.value&lt;/code&gt; keyword. By using reactive references, such as &lt;code&gt;ref&lt;/code&gt;, Vue under the hood will track any changes made to this instance and update the DOM if the value of the variable changes. An example can be seen in the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"onButtonClick"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toggle Div&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- hidden text --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"dataModel.showDiv"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Here is some hidden text&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- counter value --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;🚀 Counter value: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; 🚀&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;showDiv&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="na"&gt;counter&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;onButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel&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;showDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;dataModel&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;showDiv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel&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;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`counter: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time you click on the button, a div will be revealed/hidden, and a counter will be incremented. Such a real-world example, I know! In order to tell Vue that you want to make the &lt;code&gt;dataModel&lt;/code&gt; reactive, you need to use &lt;code&gt;ref&lt;/code&gt; otherwise, the DOM will receive no updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if I don’t use Ref?
&lt;/h2&gt;

&lt;p&gt;Coming back to the above example, you may ask, &lt;em&gt;what would happen if I use a simple object instead of the ref function?&lt;/em&gt; Let’s try to execute the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"onButtonClick"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toggle Div&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- hidden text --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"dataModel.showDiv"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Here is some hidden text&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- counter value --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;🚀 Counter value: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; 🚀&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;counter&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="na"&gt;showDiv&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showDiv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`counter: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only change is replacing the &lt;code&gt;ref&lt;/code&gt; function with a normal object. However, with the simple change, the whole DOM will stop being reactive, so any change made to the object will not be reflected in the HTML.&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%2Fns5wy0q3grbcbsrf1pbm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fns5wy0q3grbcbsrf1pbm.gif" alt="Image description" width="800" height="715"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reactive
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;reactive&lt;/code&gt; function creates a reactive object that can hold any number of properties. However, &lt;code&gt;reactive&lt;/code&gt; can't hold primitives. You will receive the following error:&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%2Fnjv1t6fwvdso0ihkf8vx.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%2Fnjv1t6fwvdso0ihkf8vx.png" alt="Image description" width="800" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the properties of this object are updated, the view is updated automatically. This powerful feature makes it easy to create complex reactive applications. Here’s an example of how to use &lt;code&gt;reactive&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"onButtonClick"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toggle Div&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- hidden text --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"dataModel.showDiv"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Here is some hidden text&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- counter value --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;🚀 Counter value: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; 🚀&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;counter&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="na"&gt;showDiv&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showDiv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`counter: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Warning&lt;/strong&gt; &lt;br&gt;
When working with the &lt;code&gt;reactive&lt;/code&gt; function, always access the object by its keys. When you try to change the &lt;code&gt;reactive&lt;/code&gt; variable reference, the reactivity will break. In the following code, you can see an example of a broken reactivity&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;counter&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;onButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Should I use Ref or Reactive?
&lt;/h3&gt;

&lt;p&gt;You will find in the documentation that ref is used mainly for primitives but also can be used for objects while reactive is only used for objects.&lt;/p&gt;

&lt;p&gt;At first glance, the main difference is just using the .value keyword when accessing the value of the ref property. However, another thing is with the implementation. Taking a look at the ref &lt;a href="https://github.com/vuejs/core/blob/main/packages/reactivity/src/ref.ts" rel="noopener noreferrer"&gt;implementation from Github&lt;/a&gt;, you can see the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RefImpl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="na"&gt;_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="na"&gt;_rawValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;

  &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Dep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
  &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;__v_isRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;__v_isShallow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_rawValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;__v_isShallow&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="nf"&gt;toRaw&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="k"&gt;this&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;__v_isShallow&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="nf"&gt;toReactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;trackRefValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_value&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nf"&gt;value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&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;useDirectValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__v_isShallow&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;isShallow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;isReadonly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;newVal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDirectValue&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;newVal&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toRaw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;hasChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_rawValue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_rawValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newVal&lt;/span&gt;
     &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useDirectValue&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;newVal&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toReactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="nf"&gt;triggerRefValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newVal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time you create a reactive variable by &lt;code&gt;ref&lt;/code&gt;, passing an object into its constructor, on line 10, it is treated as you would use the &lt;code&gt;reactive&lt;/code&gt; keyword. So should I use &lt;code&gt;ref&lt;/code&gt; or &lt;code&gt;reactive&lt;/code&gt; for objects?&lt;/p&gt;

&lt;p&gt;This is a personal preference, but I use &lt;code&gt;ref&lt;/code&gt; almost all the time. Despite tediously writing the &lt;code&gt;.value&lt;/code&gt; to access the ref’s value, the Vue team is aware of the problem, and the open &lt;a href="https://github.com/vuejs/rfcs/discussions/369" rel="noopener noreferrer"&gt;RFC - Reactivity Transform&lt;/a&gt;, was aiming to solve this issue, however, seems like it was abandoned.&lt;/p&gt;

&lt;p&gt;Reactivity transform is not yet part of the official Vue.js package, however, you can install &lt;a href="https://vue-macros.sxzz.moe/" rel="noopener noreferrer"&gt;Vue Macros&lt;/a&gt;, that enrich your VueJS experience with the  following configuration:&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;// vite.config.ts &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vitejs/plugin-vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
     &lt;span class="c1"&gt;// used to enable tranctivity transform&lt;/span&gt;
     &lt;span class="na"&gt;reactivityTransform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And use reactivity transformation from &lt;code&gt;Vue Macros&lt;/code&gt; in the following way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
 ...
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataModel1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;counter&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;dataModel2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;counter&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;onButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;dataModel2&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;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reactivity API
&lt;/h2&gt;

&lt;p&gt;Vue provides additional functions to achieve reactivity with high performance in your application. You can learn more about them on the &lt;a href="https://vuejs.org/api/reactivity-advanced.html" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;, however, it is worth highlighting two of them, which are &lt;code&gt;shallowRef&lt;/code&gt; and &lt;code&gt;shallowReactive&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ShallowRef
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;shallowRef&lt;/code&gt; function is similar to &lt;code&gt;ref&lt;/code&gt;, but with one key difference: the changes made to its properties will trigger a change only if you change the memory reference. It is used for performance optimizations of large data structures or integration with external state management systems. Looking at the official documents, the Vue community provides us with the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// does NOT trigger change&lt;/span&gt;
&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="c1"&gt;// does trigger change&lt;/span&gt;
&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Examples of when you should prefer using &lt;code&gt;shallowRef&lt;/code&gt; instead of &lt;code&gt;ref&lt;/code&gt; can be working with chart data, where you want to exclude basic reactivity for application optimization but still have reactivity if you change the data reference. Another example can be working with dynamic components, such as the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- display buttons for dynamic component --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"dynamicComponent = Comp1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Comp1&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"dynamicComponent = Comp2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Comp2&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- dynamic component --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;keep-alive&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;component&lt;/span&gt; &lt;span class="na"&gt;:is=&lt;/span&gt;&lt;span class="s"&gt;"dynamicComponent"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/keep-alive&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Comp1&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../shared/Comp1.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Comp2&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../shared/Comp2.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dynamicComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ShallowReactive
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;shallowReactive&lt;/code&gt; function is similar to &lt;code&gt;reactive&lt;/code&gt;, without nested objects, because changes made to the properties of nested objects or arrays will not trigger the update of the view. One may consider using it to get minor performance, instructing Vue that nested properties don’t have to be reactive. However, even the Vue.js team gives a warning about its usage.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt;  Shallow data structures should only be used for root level state in a component. Avoid nesting it inside a deep reactive object as it creates a tree with inconsistent reactivity behavior which can be difficult to understand and debug.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is an example of using &lt;code&gt;shallowReactive&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"onButtonClick"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Toggle Div&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- hidden text --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"dataModel.showDiv.value"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Some hidden text&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- counter value --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;🚀 Counter value: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; 🚀&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowReactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;counter&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="na"&gt;showDiv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onButtonClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// trigger reactivity&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// doesn't trigger reactivity&lt;/span&gt;
  &lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showDiv&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showDiv&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`counter: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dataModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this blog post, you learned the differences between &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;reactive&lt;/code&gt; in Vue.js. In conclusion, there are small minor differences between both of them. However, when it comes to production applications, you can use either of them.&lt;/p&gt;

&lt;p&gt;If you liked the content, hit me up with a following or feel free to reach out to me on &lt;a href="https://eduardkrivanek.com/" rel="noopener noreferrer"&gt;eduardkrivanek.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>New in Vue.js 3.3: Two-Way Binding With defineModel Macro</title>
      <dc:creator>Eduard Krivanek</dc:creator>
      <pubDate>Sat, 13 May 2023 07:39:05 +0000</pubDate>
      <link>https://dev.to/bitovi/new-in-vuejs-33-two-way-binding-with-definemodel-macro-270m</link>
      <guid>https://dev.to/bitovi/new-in-vuejs-33-two-way-binding-with-definemodel-macro-270m</guid>
      <description>&lt;p&gt;With the upcoming &lt;a href="https://github.com/vuejs/core/blob/main/CHANGELOG.md#330-2023-05-08" rel="noopener noreferrer"&gt;VueJS version 3.3&lt;/a&gt; the community once again doesn’t disappoint and releases many useful features for developers to be more productive, and ship features faster.&lt;/p&gt;

&lt;p&gt;One of the newly welcomed features is &lt;a href="https://github.com/vuejs/core/pull/8018" rel="noopener noreferrer"&gt;defineModel&lt;/a&gt; which allows us to implement much smoother 2-way binding. Let’s demonstrate its usage in the following blogpost.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is 2-Way Binding?
&lt;/h2&gt;

&lt;p&gt;Two-way binding is a feature in VueJS that allows changes in the data to update the view automatically and vice versa. This means that when the user updates the view, the underlying data is also updated, and when the data is updated programmatically, the view is automatically updated to reflect the new data. It is achieved using the &lt;code&gt;v-model&lt;/code&gt; directive, which binds a form input element to a piece of data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from Bitovi!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two-way binding is useful because it eliminates the need for manual event handling to keep the view and data in sync, which can be tedious and error-prone. Using v-model is the equivalent of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; 
      &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt; 
      &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;input=&lt;/span&gt;&lt;span class="s"&gt;"message = $event.target.value"&lt;/span&gt; 
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from Bitovi!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom 2-way binding
&lt;/h2&gt;

&lt;p&gt;An example may be having a custom search component, allowing the user to type some value into the search, which will display multiple options until he chooses one. This behavior is demonstrated in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// MySearch.vue

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- search text input --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"searchRef"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- display selected value --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"props.modelValue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Selected: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- results --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"searchRef.length &amp;gt; 3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
        &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"data in store.getLoadedElements"&lt;/span&gt;
        &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"data.id"&lt;/span&gt;
        &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"onClick(data)"&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// imports&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&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;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PropType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineEmits&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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="c1"&gt;// reference to search input&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchRef&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// fetch data from API&lt;/span&gt;
&lt;span class="nf"&gt;watchEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Element&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;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, to make the custom 2-way binding work, you use &lt;code&gt;defineProps&lt;/code&gt; to create a &lt;code&gt;modelValue&lt;/code&gt; input property for the component and you use the &lt;code&gt;defineEmits&lt;/code&gt; with &lt;code&gt;update:modelValue&lt;/code&gt; to notify the parent about the change.&lt;/p&gt;

&lt;p&gt;The usage of the above child component is achieved by the following syntax in another component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;MySearch&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"someRef"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- same as --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;MySearch&lt;/span&gt;
    &lt;span class="na"&gt;:modelValue=&lt;/span&gt;&lt;span class="s"&gt;"someRef"&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;update:modelValue=&lt;/span&gt;&lt;span class="s"&gt;"someRef = $event"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; One useful tip is that you can define multiple properties for the &lt;code&gt;MySearch&lt;/code&gt; component into the defineProps and &lt;code&gt;defineEmits&lt;/code&gt;. The name &lt;code&gt;modelValue&lt;/code&gt; is the name for the default value, however creating multiple properties, you can access them in the parent component by &lt;code&gt;&amp;lt;MySearch v-model:first="first" v-model:second="second"/&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using defineModel
&lt;/h2&gt;

&lt;p&gt;With the upcoming VueJS version, 3.3 comes a new &lt;a href="https://twitter.com/sanxiaozhizi/status/1644564064931307522" rel="noopener noreferrer"&gt;defineModel macro&lt;/a&gt;, you no longer need to write out all the above-mentioned steps to implement custom 2-way binding.&lt;/p&gt;

&lt;p&gt;This new feature is available from version-3.3.0-alpha.9, however, It is still considered an experimental feature. If you wish to use it or have difficulty upgrading to version 3.3m, you can still use its alternative, defineModels, from &lt;a href="https://vue-macros.sxzz.moe/macros/define-models.html" rel="noopener noreferrer"&gt;Vue Macros library&lt;/a&gt;, by which this feature was inspired. Overal they work the same way.&lt;/p&gt;

&lt;p&gt;After completing the &lt;a href="https://vue-macros.sxzz.moe/guide/bundler-integration.html" rel="noopener noreferrer"&gt;installation guidelines&lt;/a&gt;, you can use &lt;a href="https://vue-macros.sxzz.moe/macros/define-models.html" rel="noopener noreferrer"&gt;defineModels&lt;/a&gt; with the following syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;// MySearch.vue

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- search text input --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"searchRef"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- display selected value --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"modelValue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Selected: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- results --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"searchRef.length &amp;gt; 3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt;
        &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"data in store.getLoadedElements"&lt;/span&gt;
        &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"data.title"&lt;/span&gt;
        &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"modelValue = data"&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// imports&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;modelValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineModels&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Element&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// reference to search input&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchRef&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// fetch data from API&lt;/span&gt;
&lt;span class="nf"&gt;watchEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The macro &lt;code&gt;defineModels&lt;/code&gt; replaces the previously used &lt;code&gt;defineProps&lt;/code&gt; and &lt;code&gt;defineEmits&lt;/code&gt; into one functionality.&lt;/p&gt;

&lt;p&gt;Every time, the user passes some value to this component by &lt;code&gt;&amp;lt;MySearch :modelValue="someRef" /&amp;gt;&lt;/code&gt; the &lt;code&gt;MySearch&lt;/code&gt; component will be updated and also on the other hand, in line 16, when the user selects an element, by &lt;code&gt;modelValue = data&lt;/code&gt;, the listener on the parent component will be triggered.&lt;/p&gt;

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

&lt;p&gt;It’s great to see that the VueJS team recognizes valuable contributions from developers to the VueJS ecosystem and over time, they ship their implementation. With the upcoming version 3.3, VueJS brings us many more useful tools that will speed up our development.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>5 Tips To Improve Angular Performance</title>
      <dc:creator>Eduard Krivanek</dc:creator>
      <pubDate>Tue, 25 Apr 2023 15:39:53 +0000</pubDate>
      <link>https://dev.to/bitovi/5-tips-to-improve-angular-performance-360h</link>
      <guid>https://dev.to/bitovi/5-tips-to-improve-angular-performance-360h</guid>
      <description>&lt;p&gt;As an Angular developer, you understand the importance of building high-performing web apps. Slow loading times, sluggish UI, and poor user experience can all harm your website's reputation and deter users from returning. &lt;/p&gt;

&lt;p&gt;Fear not—there is a better way! In this blog post, you’ll learn five actionable tips that you can use immediately to boost your web application's performance. From avoiding memory leaks to running analytics outside of NgZone, let’s cover a variety of strategies to give your customers the best experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Prevent Memory Leaks
&lt;/h2&gt;

&lt;p&gt;A memory leak in an Angular application occurs when objects in the application's memory are no longer needed but are not released by the garbage collector because they are still being referenced. &lt;/p&gt;

&lt;p&gt;In the context of observables, if subscription is not unsubscribed when the component is destroyed or removed from the DOM, the observable and its associated resources will continue to exist in memory, even though they are no longer needed. Over time, this can cause a buildup of unused memory, which can slow down the application, reduce its performance, and even crash the application in extreme cases.&lt;/p&gt;

&lt;p&gt;Suppose a user uploads an image. The application stores the image data in memory until it can be saved to a database. To do this, the application uses a &lt;code&gt;Subject&lt;/code&gt; to which it subscribes when an image is uploaded. However, suppose the application does not unsubscribe from the Subject when the image has been saved to the database. In that case, the &lt;code&gt;Subject&lt;/code&gt; will continue to hold a reference to the image data in memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ImageUploaderComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;imageSubject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Subscribe to imageSubject to store uploaded images in memory&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageData&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;saveImageToDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;uploadImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Emit imageData to imageSubject&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;saveImageToDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Save image data to database&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnDestroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Memory leak occurs if we don't unsubscribe&lt;/span&gt;
    &lt;span class="c1"&gt;// Unsubscribe from imageSubject to prevent memory leaks&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&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;Additionally, as memory leaks are often difficult to diagnose, they can be frustrating for developers to troubleshoot and resolve. Therefore, Angular developers must proactively prevent memory leaks by adequately unsubscribing from observables when they are no longer needed. &lt;/p&gt;

&lt;p&gt;The most recommended way of subscribing to an observable is to use the &lt;a href="https://angular.io/api/common/AsyncPipe" rel="noopener noreferrer"&gt;Async Pipe&lt;/a&gt; or the &lt;a href="https://www.learnrxjs.io/learn-rxjs/operators/filtering/takeuntil" rel="noopener noreferrer"&gt;rxjs takeUntil&lt;/a&gt; operator.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Change Detection Strategy
&lt;/h2&gt;

&lt;p&gt;In Angular, components have two change detection strategies: Default and OnPush. The Default change detection strategy checks for changes in all components and their children on every change detection cycle, such as on any user event, typing into the form, clicking on buttons, you name it. This can be resource-intensive, especially in large applications with many components, leading to performance issues. &lt;/p&gt;

&lt;p&gt;On the other hand, the &lt;a href="https://angular.io/api/core/ChangeDetectionStrategy" rel="noopener noreferrer"&gt;OnPush change detection strategy&lt;/a&gt; only checks for changes in components if the component's input properties have changed or if an event has been triggered by the component or one of its children. This can significantly reduce the number of change detection cycles and improve the application's performance.&lt;/p&gt;

&lt;p&gt;The differences between the two strategies are demonstrated in the following pictures, where on the left, we see the Default strategy, and on the right, the OnPush change detection strategy.&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%2Fovwkp9n4d039bajsa4zx.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%2Fovwkp9n4d039bajsa4zx.png" alt="Image description" width="680" height="621"&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%2Fzn3uj7fgwj4k3wrozup7.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%2Fzn3uj7fgwj4k3wrozup7.png" alt="Image description" width="650" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In general, using the OnPush change detection strategy for components is recommended whenever possible, especially in larger applications. This can help to improve the performance and scalability of the application. Even if the Default change detection strategy may be appropriate in smaller applications or in situations where the performance impact is negligible, it is still not recommended, as it may lead to bad development practices in the long run.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Memoize Function Calls
&lt;/h2&gt;

&lt;p&gt;In Angular, function calls in the template are prohibited because they can cause performance issues. When a function is called in the template, it is re-executed every time change detection runs, like for every triggered user event, which can be very frequent in complex applications and lead to a lot of unnecessary processing and application slowdown. &lt;/p&gt;

&lt;p&gt;Consider the following scenario of having two components allowing to search for entities on the server and displaying them while calculating additional data on the frontend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-example-function-call&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
  &amp;lt;!-- search anime --&amp;gt;
  &amp;lt;app-search-anime [formControl]="animeSearchControl"&amp;gt;&amp;lt;/app-search-anime&amp;gt;

  &amp;lt;!-- table body --&amp;gt;
  &amp;lt;div *ngFor="let data of loadedAnime$ | async"&amp;gt;
    &amp;lt;!-- .... --&amp;gt;
    &amp;lt;div&amp;gt;{{ hardMathEquasionFunctionCall(data) }}&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleFunctionCallComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;animeSearchControl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FormControl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimeData&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;loadedAnime$&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnimeData&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;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadedAnime$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animeSearchControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueChanges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;curr&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;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;AnimeData&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// this function is re-executed every time an user event happens&lt;/span&gt;
    &lt;span class="nf"&gt;hardMathEquasionFunctionCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;anime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnimeData&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Function call&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;hardMathEquasion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;anime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&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;Here is a example of the above mentioned problem.&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%2Fwww.bitovi.com%2Fhs-fs%2Fhubfs%2Ffunction-calls-the-template.gif%3Fwidth%3D1440%26height%3D810%26name%3Dfunction-calls-the-template.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.bitovi.com%2Fhs-fs%2Fhubfs%2Ffunction-calls-the-template.gif%3Fwidth%3D1440%26height%3D810%26name%3Dfunction-calls-the-template.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unlike functions, which are re-executed every time change detection runs, Angular pipes are only executed when their input value changes. This means that pipes can help reduce unnecessary processing and improve the application's overall performance. Additionally, pipes are reusable and can be shared across different components, which can help to reduce code duplication and improve code maintainability.&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%2Fwww.bitovi.com%2Fhs-fs%2Fhubfs%2Fusing-angular-pipes-in-template.gif%3Fwidth%3D1440%26height%3D574%26name%3Dusing-angular-pipes-in-template.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.bitovi.com%2Fhs-fs%2Fhubfs%2Fusing-angular-pipes-in-template.gif%3Fwidth%3D1440%26height%3D574%26name%3Dusing-angular-pipes-in-template.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One quick trick to solve all your function calls in a template without rewriting them as Pipes is using Memoization. Without going deep into the topic, memoization stores the previously calculated result of the subproblem. It uses the stored result for the same subproblem, removing the extra effort to calculate again for the same problem.&lt;/p&gt;

&lt;p&gt;By understanding the concept of memorization, you can create a custom function decorator, as it is in the following code snippet, and apply it to all function call in the template so that the will behave exactly as Angular Pipes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;customMemoize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// Value cache stored in the closure&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cacheLookup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

 &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;descriptor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;originalMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;descriptor&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;descriptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// arguments can be object -&amp;gt; stringify it&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keyString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

     &lt;span class="c1"&gt;// cached data&lt;/span&gt;
     &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keyString&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;cacheLookup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cacheLookup&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;keyString&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;

     &lt;span class="c1"&gt;// call the function with arguments&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;calculation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;originalMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="c1"&gt;// save data to cache&lt;/span&gt;
     &lt;span class="nx"&gt;cacheLookup&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;keyString&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;calculation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="c1"&gt;// return calculated data&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;calculation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;descriptor&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;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.bitovi.com%2Fhs-fs%2Fhubfs%2Fmemoization-example.gif%3Fwidth%3D1440%26height%3D720%26name%3Dmemoization-example.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.bitovi.com%2Fhs-fs%2Fhubfs%2Fmemoization-example.gif%3Fwidth%3D1440%26height%3D720%26name%3Dmemoization-example.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information on how memoization can be used in Angular, check out one of our &lt;a href="https://github.com/krivanek06/example_projects/blob/main/angular_memo/src/app/example-memo/memo.ts" rel="noopener noreferrer"&gt;open-source examples&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Use RxJS Pipes for Frequent Data Updates
&lt;/h2&gt;

&lt;p&gt;It’s not a secret that we must react to user input in our application and modify, load, or send some data to the backend. The problem starts to arise when we frequently update a large data set. Let’s look at some examples and how RxJs pipes can help us.&lt;/p&gt;

&lt;h3&gt;
  
  
  DistinctUntilChanged &amp;amp; DebounceTime
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;distinctUntilChanged&lt;/code&gt; operator filters out consecutive duplicate values emitted by an observable. The debounceTime operator filters out values emitted by an observable that occur too frequently by ignoring values emitted too close together in time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-search-box&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;CommonModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactiveFormsModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;input type="text" [formControl]="searchInput"&amp;gt;
    &amp;lt;ul&amp;gt;
      &amp;lt;li *ngFor="let result of searchResults$ | async"&amp;gt;
        {{ result }}
      &amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SearchBoxComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;searchResults$&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&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="nx"&gt;searchInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FormControl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;searchService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SearchService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create an observable from the search input element&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchResults$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueChanges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="c1"&gt;// Apply the operators to the search input  &lt;/span&gt;
      &lt;span class="nf"&gt;debounceTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
      &lt;span class="nf"&gt;distinctUntilChanged&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="c1"&gt;// Call the search service to perform a search using the search term&lt;/span&gt;
      &lt;span class="nf"&gt;switchMap&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;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  BufferTime
&lt;/h3&gt;

&lt;p&gt;When having an observable that emits a large collection of values multiple times per second and causes application slowdown because of frequent UI rendering, we can opt for the &lt;code&gt;bufferTime&lt;/code&gt; operator. A real-life use case may be connected to a stock market web socket API that frequently emits data. However, we catch incoming data for &lt;code&gt;5000 milliseconds&lt;/code&gt; and then update the UI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-stock-updates&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;h2&amp;gt;Stock Updates&amp;lt;/h2&amp;gt;
    &amp;lt;div *ngFor="let update of updates"&amp;gt;{{ update }}&amp;lt;/div&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StockUpdatesComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;updates$&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&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="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Connect to the WebSocket endpoint that emits stock market updates&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;webSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wss://example.com/updates&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Apply the bufferTime operator to the WebSocket observable&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updates$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;bufferTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="c1"&gt;// Concatenate the buffered updates and add them to the updates array&lt;/span&gt;
        &lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;curr&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;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other RxJs operators that can be useful to worth with frequent data emotions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.learnrxjs.io/learn-rxjs/operators/filtering/audittime" rel="noopener noreferrer"&gt;auditTime&lt;/a&gt; - ignores the source observable for a given amount of time&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.learnrxjs.io/learn-rxjs/operators/filtering/throttletime" rel="noopener noreferrer"&gt;throttleTime&lt;/a&gt; - ignores subsequent source values for provided milliseconds&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  RunOursideAngular
&lt;/h3&gt;

&lt;p&gt;The runOutsideAngular method is helpful when short-lived heavy computations need to be executed within an Angular application, such as when performing data processing, rendering large datasets, or working with complex algorithms. &lt;/p&gt;

&lt;p&gt;By executing these computations outside the Angular zone, the application can remain responsive and provide a smooth user experience.&lt;/p&gt;

&lt;p&gt;A real-world use case for &lt;code&gt;ngZone.runOutsideAngular&lt;/code&gt; might be a large file upload or download or a complex data processing task that requires significant processing time. By running these tasks outside Angular's change detection, we can ensure that the application remains responsive and doesn't freeze up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;input type="file" (change)="onFileChange($event)"&amp;gt;
    &amp;lt;button (click)="uploadImage()"&amp;gt;Upload Image&amp;lt;/button&amp;gt;
    &amp;lt;div *ngIf="uploadResult"&amp;gt;Result: {{ uploadResult }}&amp;lt;/div&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;uploadResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;ngZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NgZone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;imageUploadService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImageUploadService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ChangeDetectorRef&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;onFileChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get the selected file from the input element&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&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="c1"&gt;// Pass the file to the image upload service to prepare for upload&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageUploadService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepareImageForUpload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;uploadImage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Call the image upload service to upload the prepared image&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ngZone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;runOutsideAngular&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// uploading images &amp;lt;-- blocking operation, may freez up the UI&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imageUploadService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uploadImage&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Update the component state with the upload result&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ngZone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploadResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="c1"&gt;// Manually trigger change detection&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;detectChanges&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; It is essential to note that any changes made during the execution of the heavy computation will not trigger change detection, and developers will need to trigger change detection if necessary manually.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5. Web Workers for Heavy Computation
&lt;/h2&gt;

&lt;p&gt;For heavy computation that may run through the whole lifecycle of the application, we can opt for web workers. Web workers are designed to execute heavy computations in separate threads, which can significantly improve the performance and responsiveness of the application and user experience. &lt;/p&gt;

&lt;p&gt;However, using web workers requires more setup and coordination than using &lt;code&gt;runOutsideAngular&lt;/code&gt;, as developers must manage multiple threads and handle communication between them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// my-worker.ts&lt;/span&gt;

&lt;span class="c1"&gt;// Define a function that will be executed in the web worker&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;doHeavyComputation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Perform some heavy computation here&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Set up a message listener to receive messages from the main thread&lt;/span&gt;
&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// When a message is received, extract the data from the event&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&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="c1"&gt;// Call the function and return the result to the main thread&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;doHeavyComputation&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;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// my-component.component.ts&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-my-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Result: {{ result }}`&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create a new instance of the Worker class&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;worker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./my-worker.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Set up a message listener to receive messages from the web worker&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// When a message is received, extract the data &lt;/span&gt;
      &lt;span class="c1"&gt;// from the event and update the component state&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// Send a message to the web worker&lt;/span&gt;
    &lt;span class="nx"&gt;worker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are writing a web worker that uses CommonJS modules instead of ES modules, you can specify this by setting &lt;code&gt;{ type: 'classic' }&lt;/code&gt; instead of &lt;code&gt;{ type: 'module' }&lt;/code&gt;. However, ES modules are generally recommended unless you have a specific reason to use CommonJS modules.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; Note that web workers have some restrictions on what APIs are available to them (for example, they don't have access to the DOM), so you may need to modify your code accordingly. Additionally, you may want to handle errors and other edge cases to ensure that your web worker is robust and reliable.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;In this blog post, you learned how to identify common issues in your Angular application and saw potential solutions. Angular is a large ecosystem. It provides lots of features, hovewer it is very easy to make a mistake a build up the tech debt that may eventually slow down your release and competitive advantage.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>GraphQL: Everything You Need to Know</title>
      <dc:creator>Eduard Krivanek</dc:creator>
      <pubDate>Mon, 13 Mar 2023 06:16:29 +0000</pubDate>
      <link>https://dev.to/bitovi/graphql-everything-you-need-to-know-1nbm</link>
      <guid>https://dev.to/bitovi/graphql-everything-you-need-to-know-1nbm</guid>
      <description>&lt;p&gt;Are you thinking about designing a backend API? You probably already know about REST architecture. You might even know that the REST architecture doesn’t handle complex applications very well.&lt;/p&gt;

&lt;p&gt;If so, you might be struggling to answer the following questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How much data should I return with each endpoint?&lt;/li&gt;
&lt;li&gt;Will I return the same data on mobile as to desktop devices?&lt;/li&gt;
&lt;li&gt;Do I want to have real-time updates if something changes?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enter &lt;strong&gt;GraphQL&lt;/strong&gt;. In this post, learn everything you need to know about GraphQL. Discover GraphQL’s benefits and limitations and decide whether it’s the right tool for your backend API project. 🙌&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem With REST
&lt;/h2&gt;

&lt;p&gt;REST stands for &lt;strong&gt;RE&lt;/strong&gt;presentational &lt;strong&gt;S&lt;/strong&gt;tate &lt;strong&gt;T&lt;/strong&gt;ransfer, where endpoints are structured around objects, like users, groups, comments, etc.&lt;/p&gt;

&lt;p&gt;REST is a specification that has been around for a long time, and today it’s still the most standard, widely-accepted way to write an API. Despite REST maturity, the main issue spins around one question.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What data should I return by my endpoints?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One business case you might encounter is a need to display a list of users and a list of each user’s recently added comments.&lt;/p&gt;

&lt;p&gt;In other words, fetch a list of entities, and for each entity, fetch another related list of entities. There are two ways of solving this problem using REST.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modeling Endpoints Around Resources
&lt;/h2&gt;

&lt;p&gt;Having one endpoint per resource is a very maintainable approach for backend developers. It is relatively scalable but introduces unnecessary complexity on the client side, meaning the client needs to make multiple API calls to structure a data model. In this example, you could have the following endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getUsers()&lt;/code&gt; - return a list of users&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getCommentsByUserId(userId: string)&lt;/code&gt; - returns a list of comments for a specific userId&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using a resource-based approach, a relatively common &lt;a href="https://restfulapi.net/rest-api-n-1-problem/#:~:text=N%2B1%20Problem%20in%20REST%20APIs&amp;amp;text=In%20the%20case%20of%20web,collection%20resource%20%2B%20N%20child%20resources" rel="noopener noreferrer"&gt;N + 1&lt;/a&gt; problem can arise, where the client side is required to call the server N + 1 times to fetch one collection of resource + N child resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUserWithComments&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// fetch a list of users&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// new HTTP request for each user&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="c1"&gt;// loading comments from the server&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getCommentsByUserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;users&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;Resource-based endpoints may lead to slow rendering because it takes time to load all the data, and you can overload the server with too many API calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Returning the Exact Needed Shape of the Data
&lt;/h2&gt;

&lt;p&gt;Endpoints can also be structured to return the exact shape of data the client wants to work with. You could have an endpoint, such as getUsersWithComments(), that would return users with their comments in one HTTP round trip. This approach works until it doesn’t.&lt;/p&gt;

&lt;p&gt;This approach establishes a close relationship between the client and the server. Whenever the management requests to change the UI, where additional data should be displayed or removed, the frontend developers have to contact backend developers to adjust the returning data from a specific endpoint.&lt;/p&gt;

&lt;p&gt;This approach is challenging to maintain, especially when considering having multiple endpoints that return some mixed data type for the consumer or having separate endpoints for mobile devices. In the worst case, you could end up with too many endpoints returning a combination of objects, not knowing which endpoints are even used.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are My Options?
&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%2Fiqn7uyo0nxfz0wprsjbn.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%2Fiqn7uyo0nxfz0wprsjbn.png" alt="Image description" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Delegating the responsibility of defining the returning data shape to the server side, sooner or later, the frontend developers will encounter one of the two problems mentioned above. To put gas into the fire, the following problems in the REST architecture weren’t even mentioned :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sending fewer data to mobile users&lt;/li&gt;
&lt;li&gt;Having real-time communication&lt;/li&gt;
&lt;li&gt;Having API documentation (and following it)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The groundwork has been laid. Let’s talk about GraphQL!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is GraphQL?
&lt;/h2&gt;

&lt;p&gt;GraphQL is a query language that delegates the responsibility of defining the shape of data being returned from the server to the client by the client. The server provides a playground and documentation for its API, where the client can see all available executable methods. Queries to get data, mutations to modify data, and subscriptions for real-time communication (we will get back to it later).&lt;/p&gt;

&lt;p&gt;When calling a server-side method, a JSON data structure is included in the message payload that describes the returning object property fields for which the server has to return value.&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%2F2ezww91t09q8ptyo688c.jpeg" 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%2F2ezww91t09q8ptyo688c.jpeg" alt="Image description" width="544" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because GraphQL solves under-fetching and over-fetching, the client only gets back data for fields that are included in the payload of the HTTP request. No more, no less.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL Models Relationships ❤️
&lt;/h2&gt;

&lt;p&gt;GraphQL models a relationship between objects. It enables retrieving all required data by one HTTP round trip. Relationship modeling means if an entity has a 1-to-N relationship with another one, we can request this relational information in one query.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL Resolvers
&lt;/h2&gt;

&lt;p&gt;To resolve object relationships, you guessed it, resolvers are used. A resolver is a function, the main building block why we even consider using GrapQL in the first place, that's responsible for populating the data for a single field for the object type.&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%2F18b9jch81dq4mhlozu9f.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%2F18b9jch81dq4mhlozu9f.png" alt="Image description" width="470" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resolvers can be understood as an enhancement to add additional fields for an entity class that doesn’t exist in the database but is calculated on the server side.&lt;/p&gt;

&lt;p&gt;Their usefulness lies in their execution. A function registered as a Resolver is not executed until it is called. The code snippet below represents a piece of the above-displayed database UML diagram using the NestJS framework.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Movie&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&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;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;nullable&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="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User's title to the movie&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;defaultValue&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="nx"&gt;title&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;nullable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User's description to the movie&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="nx"&gt;description&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="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Resolver&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;Movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MovieResolver&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;movieCommentService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MovieCommentService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;ResolveField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;movieComment&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;MovieComment&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getMovieComment&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Parent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;movieCommentService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllMovieCommetsByMovieId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="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;Loading comments for a &lt;code&gt;Movie&lt;/code&gt; object require making an expensive database select operation. Furthermore, you don't always need to load comments for a Movie, only when the user requires them.&lt;/p&gt;

&lt;p&gt;Decorating a method with the &lt;code&gt;@ResolveField&lt;/code&gt; decorator (NestJS syntax) executes the inside logic only when the client requests data for that field name, in this case, for &lt;code&gt;movieComment&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; The API creator should provide descriptions for resolver fields, especially the ones that execute an expensive server-side operation, like database calls, so that the consumers won’t query unnecessary fields just because they can.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Benefits of GraphQL
&lt;/h2&gt;

&lt;p&gt;In the REST architecture, the question that is always present is, “What data does this endpoint return?”. Testing endpoints by Postman, or in better cases, having &lt;a href="https://swagger.io/" rel="noopener noreferrer"&gt;swagger&lt;/a&gt; for backend documentation, still doesn’t guarantee that the returned Object’s properties will not be &lt;code&gt;undefined&lt;/code&gt; and are the type that the documentation describes. For a better developer experience, GraphQL provides the following advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GraphQL playground&lt;/li&gt;
&lt;li&gt;Predefined schema&lt;/li&gt;
&lt;li&gt;Generating TypeScript types&lt;/li&gt;
&lt;li&gt;Real-time communication&lt;/li&gt;
&lt;li&gt;Device adaptations&lt;/li&gt;
&lt;li&gt;Batch query execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest major benefit worth highlighting is &lt;strong&gt;GraphQL decouples the dependency between the server and the consumer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The consumer only receives back values for fields included in the GraphQL operation. The server can create a very complex schema and offer a return type that has 60+ properties to query, but the consumer will only receive back values for the fields which were included in the GraphQL operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL Playground
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/graphql/graphql-playground" rel="noopener noreferrer"&gt;GraphQL Playground&lt;/a&gt; is an IDE created and maintained by Prisma. It’s built on top of GraphQL and serves as API documentation for every available query, mutation, and subscription. The consumer can inspect the return type of each operation and test server-side functionalities. For an open API, check out SpaceX GraphQL 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%2Fihygxfkzjzowkbqd5ey7.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%2Fihygxfkzjzowkbqd5ey7.png" alt="Image description" width="694" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Predefined Schema
&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%2Fnx5pm3vwz9a8fs5l5ma0.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%2Fnx5pm3vwz9a8fs5l5ma0.png" alt="Image description" width="340" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When inspecting GraphQL data types throughout the playground, you might notice some fields include an exclamation mark. &lt;code&gt;(!)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It serves as insurance that the server has to provide the correct data type and can not return a &lt;code&gt;null&lt;/code&gt; value for them.&lt;/p&gt;

&lt;p&gt;Taking a look at the attached image by querying fields like &lt;code&gt;User.id&lt;/code&gt;, &lt;code&gt;User.createdAt&lt;/code&gt;, the server will never return a null value for these fields. If it had happened, we would receive the following error from the query operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;errors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cannot return null for non-nullable field User.id.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;statusCode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;"&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;Using array types, like for the &lt;code&gt;movieCommentsUserLeft: [MovieComment!]!&lt;/code&gt;, the outer exclamation mark, &lt;code&gt;[]!&lt;/code&gt; means that the API will always return back a list of values, even an empty list, and the returned value will never be &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the other hand, the inner exclamation mark &lt;code&gt;[MovieComment!]&lt;/code&gt; describes that the elements inside the list will always be objects. It is impossible for a &lt;code&gt;null&lt;/code&gt; value to be part of the list. If it had happened, the whole query would fail, and no data would have been returned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating TypeScript Types
&lt;/h2&gt;

&lt;p&gt;The major benefit of the exposed GraphQL schema is that developers define GraphQL operations and use libraries, such as &lt;a href="https://the-guild.dev/graphql/codegen" rel="noopener noreferrer"&gt;graphql-code-generator&lt;/a&gt;, that allow generating TypeScript types from the server-side schema.&lt;/p&gt;

&lt;p&gt;Using a generator prevents manual handwriting of TypeScript Interfaces for all API responses, and if the server-side schema change, the whole TypeScript schema can be regenerated by one command.&lt;/p&gt;

&lt;p&gt;An example can be seen in the image below, where at the left, we define a query operation &lt;code&gt;launchesPast&lt;/code&gt; expecting a &lt;code&gt;LaunchLast&lt;/code&gt; fragment to be returned, and on the right, we see the generated TypeScript types by &lt;a href="https://the-guild.dev/graphql/codegen" rel="noopener noreferrer"&gt;graphql-code-generator&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%2Fkyc60s02hz254pw3sbm3.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%2Fkyc60s02hz254pw3sbm3.png" alt="Image description" width="544" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://graphql.org/learn/queries/#fragments" rel="noopener noreferrer"&gt;GrapQL fragments&lt;/a&gt;, we can share pieces of logic in multiple queries and mutations that will return the same data type. Generated fragments can then be used for type-checking on the client side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-Time Communication
&lt;/h2&gt;

&lt;p&gt;In the traditional REST world, to achieve real-time communication, you need to use WebSockets. You know they suck. What endpoint should I listen to? What data will I receive back? Is the connection alive? &lt;/p&gt;

&lt;p&gt;Instead of &lt;a href="https://www.apollographql.com/docs/react/data/queries/#polling" rel="noopener noreferrer"&gt;Polling data&lt;/a&gt; from the server, &lt;a href="https://www.apollographql.com/docs/react/data/subscriptions/" rel="noopener noreferrer"&gt;subscriptions&lt;/a&gt; are used to listen to asynchronous emitted events. Subscriptions maintain an active connection to the server, listening and waiting for the server to push updates. The main benefit of using subscriptions is the type safety, such that, as in queries, the consumer can select which fields to receive values back.&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%2Ft05ncdxut0kqqu949z1m.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%2Ft05ncdxut0kqqu949z1m.png" alt="Image description" width="544" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Device Adaptations
&lt;/h2&gt;

&lt;p&gt;This is more or less just a piece of advice. When working on a small screen device, like a mobile phone, you usually don’t show as much data compared to a desktop resolution. Therefore it is not required to fetch as much data as a desktop device.&lt;/p&gt;

&lt;p&gt;The solution you may go with is to create two separate queries for the same operation, one for a desktop device to fetch a large quantity of data and one for a mobile device to load less data and use conditional statements to execute them based on the client’s device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Batch Query Execution
&lt;/h2&gt;

&lt;p&gt;Having a GraphQL API, you can execute multiple queries at once by sending one HTTP request. Taking a look at &lt;a href="https://api.spacex.land/graphql/" rel="noopener noreferrer"&gt;SpaceX API&lt;/a&gt;, you can select multiple independent queries and fetch data in one round trip.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;launchesPast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&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="nx"&gt;mission_name&lt;/span&gt;
    &lt;span class="nx"&gt;launch_date_local&lt;/span&gt;
    &lt;span class="nx"&gt;launch_site&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;site_name&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;historiesResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&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="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;details&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;missions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&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="nx"&gt;name&lt;/span&gt;
    &lt;span class="nx"&gt;twitter&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Drawbacks of GraphQL
&lt;/h2&gt;

&lt;p&gt;There has never been a point in time when technology was so great that it would not have any downside. Let’s take a look at some concerns you have to be aware of when choosing GraphQL architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  N + 1 Problem
&lt;/h2&gt;

&lt;p&gt;Once you start learning about GraphQL, the first problem you hear about is the “N+1 problem”. Let’s describe an example scenario by the SpaceX API of how it may happen.&lt;/p&gt;

&lt;p&gt;You want to fetch past &lt;code&gt;launches&lt;/code&gt; from one table, and for each of them, you want to get the &lt;code&gt;site_name&lt;/code&gt; from another table. Using REST, you may have the following endpoint.&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="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/launches/past&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;queryParam&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;limit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that could result in the following Database calls&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="nx"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;FROM&lt;/span&gt; &lt;span class="nx"&gt;launches&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;fetched&lt;/span&gt; &lt;span class="nx"&gt;launches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ids&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;
&lt;span class="nx"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;FROM&lt;/span&gt; &lt;span class="nx"&gt;launch_sites&lt;/span&gt; &lt;span class="nx"&gt;WHERE&lt;/span&gt; &lt;span class="nx"&gt;launch_id&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With two queries, you will have your desired result. Beware that this works because you have already loaded a list of &lt;code&gt;launches&lt;/code&gt;, and you pass their &lt;code&gt;launch.id&lt;/code&gt; to the second query.&lt;/p&gt;

&lt;p&gt;In GraphQL, to load &lt;code&gt;launch_sites&lt;/code&gt; from a different table, you would probably use resolvers attached to the &lt;code&gt;Launch&lt;/code&gt; entity, like in the following snippet.&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="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`{
  type Query {
launchesPast(limit: Int!): [Launch!]!
  } 

  # from table launches
  type Launch {
    id: Int!
    mission_name: String 
    launch_site: [Launch_sites!]!
  } 

  # from table launch_sites
  type Launch_sites {
    id: Int! 
    site_name: String
  }
}`&lt;/span&gt;

&lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;launchesPast&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="na"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;limit&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="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllLaunches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nl"&gt;Launch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;launch_site&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;launchObj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&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;ORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLaunchSitesById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;launchObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, suppose you execute the below query. In that case, you will create N database calls for N &lt;code&gt;Launches&lt;/code&gt; to get their &lt;code&gt;site_name&lt;/code&gt; because every resolver function only knows about its parent, and GraphQL executes a separate resolver function for every field.&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="nx"&gt;query&lt;/span&gt; &lt;span class="nc"&gt;LaunchesPastQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;launchesPast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;fetches&lt;/span&gt; &lt;span class="nx"&gt;Launch&lt;/span&gt; &lt;span class="nf"&gt;entities &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;
      &lt;span class="nx"&gt;mission_name&lt;/span&gt;
      &lt;span class="nx"&gt;launch_site&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;fetches&lt;/span&gt; &lt;span class="nx"&gt;Sites&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nc"&gt;Launch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt; &lt;span class="nx"&gt;queries&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;N&lt;/span&gt; &lt;span class="nx"&gt;Launches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nx"&gt;site_name&lt;/span&gt;   
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;                           &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Therefore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;round&lt;/span&gt; &lt;span class="nx"&gt;trips&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will translate to the following pseudo-SQL:&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="nx"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;FROM&lt;/span&gt; &lt;span class="nx"&gt;launches&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nx"&gt;pass&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;fetched&lt;/span&gt; &lt;span class="nx"&gt;launches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ids&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;
&lt;span class="nx"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;FROM&lt;/span&gt; &lt;span class="nx"&gt;launch_sites&lt;/span&gt; &lt;span class="nx"&gt;WHERE&lt;/span&gt; &lt;span class="nx"&gt;launch_id&lt;/span&gt; &lt;span class="k"&gt;in &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="nx"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;FROM&lt;/span&gt; &lt;span class="nx"&gt;launch_sites&lt;/span&gt; &lt;span class="nx"&gt;WHERE&lt;/span&gt; &lt;span class="nx"&gt;launch_id&lt;/span&gt; &lt;span class="k"&gt;in &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="nx"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;FROM&lt;/span&gt; &lt;span class="nx"&gt;launch_sites&lt;/span&gt; &lt;span class="nx"&gt;WHERE&lt;/span&gt; &lt;span class="nx"&gt;launch_id&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The N+1 problem is further exacerbated in GraphQL because neither clients nor servers can predict how expensive a request is until it’s executed. In REST, costs are predictable because there’s one trip per endpoint requested. In GraphQL, there’s only one endpoint, and it’s not indicative of the potential size of incoming requests.&lt;/p&gt;

&lt;p&gt;Facebook previously introduced a solution to the N+1 issue by creating &lt;a href="https://github.com/graphql/dataloader" rel="noopener noreferrer"&gt;DataLoader&lt;/a&gt;, a library that batches requests specifically for JavaScript. Also, Shopify took DataLoader as inspiration and built the &lt;a href="https://github.com/Shopify/graphql-batch" rel="noopener noreferrer"&gt;GraphQL Batch&lt;/a&gt; Ruby library.&lt;/p&gt;

&lt;p&gt;What DataLoader does is wait for all resolvers to load in their individual keys and then hit the database once with the keys, and return a promise that resolves an array of the values. It batches queries instead of executing them one at a time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; N+1 is the biggest problem you may encounter by having a GraphQL server. Before implementing the server-side logic, you need to have a rough understanding of how entity relationships will be resolved because once you deal with a large database and millions of data, having a bad implementation will hugely increase your tech debt and massively impact the performance of the application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Schema Dependency
&lt;/h2&gt;

&lt;p&gt;Having a predefined schema that is being exchanged between the server and the consumer is advantageous, even so, when the exclamation mark (!) is used on type fields so that the consumer knows which fields will never have a null value.&lt;/p&gt;

&lt;p&gt;Exclamation marks or so-called not-null values can, however, ruin the whole query. Let’s have an example that, for some Launch entity, it saved ID column in the database, or any column that must have a present value, will suddenly be null (code snippet on line 17.).&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="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`{
  type Query {
    launchesPast: [Launch!]!
  } 

  # from table launches
  type Launch {
    id: Int!
    mission_name: String 
  } 
}`&lt;/span&gt;

&lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;launchesPast&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="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;allLaunches&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;ORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllLaunches&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="nx"&gt;allLaunches&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="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- will cause the query to fail&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;allLaunches&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the consumer requests a list of &lt;code&gt;Launch&lt;/code&gt; entities by the &lt;code&gt;launchesPast&lt;/code&gt; query, the whole query will fail and you will receive the following error message:&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="nx"&gt;Cannot&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;nullable&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt; &lt;span class="nx"&gt;Launch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, if you query a list of objects, and only one of them does not match the returning schema (it has a &lt;code&gt;null&lt;/code&gt; value for a field that has the exclamation mark &lt;code&gt;(!)&lt;/code&gt;), then your whole query will fail, and you will not receive back any data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nested Recursion
&lt;/h2&gt;

&lt;p&gt;As a query language for APIs, GraphQL gives clients the power to execute queries to get exactly what they need. But what if a client sends a query asking for many fields and resources? With GraphQL, users can’t simply run any query they want.&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="nx"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;books&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt;
    &lt;span class="nx"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;
      &lt;span class="nx"&gt;books&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;title&lt;/span&gt;
        &lt;span class="nx"&gt;authors&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think you can see the problem here. A GraphQL API must be carefully designed, and to prevent such a nested data loading, you can use libraries like &lt;a href="https://github.com/pa-bru/graphql-cost-analysis" rel="noopener noreferrer"&gt;graphql-cost-analysis&lt;/a&gt; to set a &lt;code&gt;maximumCost&lt;/code&gt; for your whole schema and, for each operation, define a &lt;code&gt;complexity&lt;/code&gt; value. So when the consumer uses your API, the sum of all complexity from each operation can not exceed the total &lt;code&gt;maximumCost&lt;/code&gt;. Otherwise, the consumer’s request will be blocked.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP Status Codes
&lt;/h2&gt;

&lt;p&gt;Whenever Apollo Server encounters errors while processing a GraphQL operation, its response to the client includes an errors array containing each error that occurred. Despite any occurred error, the status code of each request will have a code 200, but the returned payload will have a list of occurred errors with the &lt;code&gt;statusCode&lt;/code&gt; of 500.&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%2Ff2yeuxn2u66xfmqi59am.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%2Ff2yeuxn2u66xfmqi59am.png" alt="Image description" width="376" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Error code 500 is not necessarily the best way to notify your consumers that something went wrong. You want to use status codes for unauthenticated/unauthorized requests, redirects, etc. For information on configuring error handling on the server side, check out &lt;a href="https://www.apollographql.com/docs/apollo-server/data/errors/" rel="noopener noreferrer"&gt;Apollo server Error handling&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaling with Subscriptions
&lt;/h2&gt;

&lt;p&gt;As previously mentioned in the &lt;strong&gt;Real-time Communication&lt;/strong&gt; section, subscriptions are a helpful feature in GraphQL for asynchronous emitted events from the server side. The problem is with scaling the server horizontally into multiple instances to manage request overload.&lt;/p&gt;

&lt;p&gt;If you use subscriptions to notify a group of users and you have multiple instances of your backend application, you never want your clients to be directly connected to a specific instance. What may happen is that one GraphQL instance pushes data via subscription, but clients who are connected to a different instance will not be notified about that change. Consider using &lt;code&gt;https://redis.io/&lt;/code&gt; as your &lt;a href="https://www.cloudflare.com/en-gb/learning/performance/what-is-load-balancing/" rel="noopener noreferrer"&gt;load-balancer&lt;/a&gt;. Read more about GraphQL subscriptions with Redis Pub Sub.&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%2Fxj1vvbzi9t18scl8nkee.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%2Fxj1vvbzi9t18scl8nkee.png" alt="Image description" width="442" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Do I need a GraphQL server?
&lt;/h2&gt;

&lt;p&gt;The battle between GraphQL vs REST has been ongoing for quite some time. Primarily because these two API styles have different approaches when dealing with data transfer over internet protocols.&lt;/p&gt;

&lt;p&gt;For most applications, there won’t be any increase in performance by simply migrating to GraphQL. However, when an app starts to scale, that is when the value of migrating to GraphQL comes to play. It presents a powerful and elegant solution for teams that have been restricted to the traditional REST API. Also, a common case for a GraphQL can be to hide multiple complex systems behind it, legacy infrastructures, or third-party APIs that are enormous in size and difficult to maintain and handle.&lt;/p&gt;

&lt;p&gt;When considering the adaption of GraphQL, it may be useful to read the journeys of other companies implementing it. You may be interested in &lt;a href="https://medium.com/paypal-tech/graphql-at-paypal-an-adoption-story-b7e01175f2b7" rel="noopener noreferrer"&gt;PayPal's Adoption of GraphQL&lt;/a&gt;, &lt;a href="https://netflixtechblog.com/beyond-rest-1b76f7c20ef6" rel="noopener noreferrer"&gt;Netflix's Rapid Development with GraphQL Microservices&lt;/a&gt;, or &lt;a href="https://www.shopify.com/partners/blog/graphql-admin-api?utm_source=thenewstack&amp;amp;utm_medium=website&amp;amp;utm_content=inline-mention&amp;amp;utm_campaign=platform" rel="noopener noreferrer"&gt;Shopify's New Admin API in GraphQL&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Choosing the right tech stack or architecture design for an application is never an easy decision. You have to consider the problems each decision solves and the complexity it brings.&lt;/p&gt;

&lt;p&gt;Through this article, you learned what GraphQL is, why developers, especially frontend developers, love it so much, how it can improve your development journey, and also what concerns to be aware of.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Angular &amp; Apollo Client: Apollo Cache Configuration</title>
      <dc:creator>Eduard Krivanek</dc:creator>
      <pubDate>Mon, 02 Jan 2023 14:30:17 +0000</pubDate>
      <link>https://dev.to/bitovi/angular-apollo-client-apollo-cache-configuration-1d95</link>
      <guid>https://dev.to/bitovi/angular-apollo-client-apollo-cache-configuration-1d95</guid>
      <description>&lt;p&gt;&lt;a href="https://www.apollographql.com/docs/react/" rel="noopener noreferrer"&gt;Apollo-client&lt;/a&gt; might be a go-to library for connecting a frontend application to a GraphQL server; however, it was initially built as a comprehensive state management library. The Apollo client’s cache allows persisting local data both with reactive variables and client cache queries and can extend server-side objects with local properties. &lt;/p&gt;

&lt;p&gt;By the end of this post, you will have a solid understanding of how Apollo client cache works, but if you are unfamiliar with Apollo, check out &lt;a href="https://www.bitovi.com/blog/angular-and-apollo-client-get-started-with-graphql-in-angluar" rel="noopener noreferrer"&gt;Angular &amp;amp; Apollo Client: Getting Started with GraphQL in Angular&lt;/a&gt; or &lt;a href="https://github.com/krivanek06/graphql_example" rel="noopener noreferrer"&gt;go through the source code on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extending GraphQL Schema with Local Data
&lt;/h2&gt;

&lt;p&gt;To store client-side information in objects received from a GraphQL server, you can use a &lt;a href="https://www.apollographql.com/docs/react/local-state/managing-state-with-field-policies" rel="noopener noreferrer"&gt;local-only field&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s have an example for extending a server-side Movie object, which has fields like Id, title, etc., with an additional isSelected property, allowing selecting any movie to perform some logical operation on the chosen entities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="c"&gt;# Original Movie type provided by the server&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;movieComment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MovieComment&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generating Types
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;{{name}}.graphql&lt;/code&gt; file where you tell &lt;a href="https://www.graphql-code-generator.com/" rel="noopener noreferrer"&gt;graphql-code-generator&lt;/a&gt; how you want to extend the server-side schema. Include your file location into the codegen.yml file under the schema section which instructs graphql-code-generator to inspect locally-defined GraphQL types and merge them with the server-side schema.&lt;/p&gt;

&lt;p&gt;In this example, you create a local.schema.graphql file in which you extend a Movie type with an isSelected: MovieSelectType! field. The isSelected field will be a local attribute for the Movie object that doesn’t initially exist when you first fetch a list of Movie objects from the server side. &lt;/p&gt;

&lt;p&gt;Despite that, you mark the isSelected field as required using the exclamation mark (!), and you will configure the Apollo client to always return some value for it. You include the local.schema.graphql file location under the schema property in codegen.yml.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="c"&gt;# src/graphql/graphql-local-schema/local.schema.graphql&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;enum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MovieSelectType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;SELECTED&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;UNSELECTED&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;extend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;isSelected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MovieSelectType&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# codegen.yml&lt;/span&gt;

&lt;span class="na"&gt;generates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# where to generate file&lt;/span&gt;
  &lt;span class="na"&gt;./src/app/graphql/graphql-custom-backend.service.ts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# where the server lives&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;http://localhost:3001/graphql&lt;/span&gt;
      &lt;span class="c1"&gt;# where is our local schema&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/app/graphql/graphql-local-schema/*.graphql&lt;/span&gt; 
    &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the script &lt;code&gt;npm run generate-types&lt;/code&gt; ("generate-types": "graphql-codegen --config codegen.yml") will generate an additional isSelected field on the Movie type.&lt;/p&gt;

&lt;p&gt;Simply querying the isSelected field would throw an error Cannot query field "isSelected" on type "Movie", because the Apollo client expects isSelected to be provided by the server. &lt;/p&gt;

&lt;p&gt;You must add the &lt;code&gt;@client&lt;/code&gt; decorator, which tells Apollo-client to skip server-side validation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;fragment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MovieInfo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;isSelected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;@client&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reading Local Only Fields
&lt;/h3&gt;

&lt;p&gt;Though you no longer get an error after registering &lt;code&gt;isSelected&lt;/code&gt; as a local-only field, inspecting the server-side Movie objects by &lt;a href="https://chrome.google.com/webstore/detail/apollo-client-devtools/jdkknkkbebbapilgoeccciglkfbmbnfm" rel="noopener noreferrer"&gt;Apollo Client Devtools&lt;/a&gt;, you see that they do not contain the &lt;code&gt;isSelected&lt;/code&gt; property.&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%2Fljietmaa9f1vjqmpvm4d.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%2Fljietmaa9f1vjqmpvm4d.png" alt="Image description" width="693" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you had called Movie.isSelected you would get undefined. To customize how a particular field is read, you use the &lt;a href="https://www.apollographql.com/docs/react/caching/cache-field-behavior/" rel="noopener noreferrer"&gt;field policy&lt;/a&gt; field in Apollo’s InMemoryCache.&lt;/p&gt;

&lt;p&gt;The right place to define a return value for local-only fields is to implement a &lt;a href="https://www.apollographql.com/docs/react/caching/cache-field-behavior/#the-read-function" rel="noopener noreferrer"&gt;read(...) function&lt;/a&gt;, that the Apollo client always executes by default when you call a specific GraphQL object property. The read(...) function in its argument provides the actual object’s property value and it must return the same data type as the property. &lt;/p&gt;

&lt;p&gt;In this example, the &lt;code&gt;selectType&lt;/code&gt; for &lt;code&gt;read(selectType?: MovieSelectType)&lt;/code&gt; at its initial state is &lt;code&gt;undefined&lt;/code&gt;, since the server doesn’t resolve any data for that field, so you return a default &lt;code&gt;MovieSelectType.Unselected&lt;/code&gt; value. However, if you later set the &lt;code&gt;selectType&lt;/code&gt; property for a Movie object, you return the current value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InMemoryCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;typePolicies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="na"&gt;isSelected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectType&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;MovieSelectType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;selectType&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;MovieSelectType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Unselected&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Client-Side Schema
&lt;/h2&gt;

&lt;p&gt;Another common use case for cache manipulation is storing local, client-side data in the Apollo client cache as a single source of truth. Use cases might include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Storing system configuration&lt;/li&gt;
&lt;li&gt;Storing edited form state&lt;/li&gt;
&lt;li&gt;Storing filtered table state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A practical use for Angular developers is to persist local data in Apollo’s cache using one of two approaches: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Directly &lt;a href="https://www.apollographql.com/docs/react/caching/cache-interaction" rel="noopener noreferrer"&gt;write and read&lt;/a&gt; from the cache&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://www.apollographql.com/docs/react/local-state/reactive-variables" rel="noopener noreferrer"&gt;reactive variables&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s take a look at both of these methods&lt;/p&gt;

&lt;h3&gt;
  
  
  Extending Type Query
&lt;/h3&gt;

&lt;p&gt;You first need to provide a &lt;a href="https://www.apollographql.com/docs/react/local-state/client-side-schema" rel="noopener noreferrer"&gt;client-side schema&lt;/a&gt;, meaning you register queries, which will be used only on the client side of the application. Registering additional queries can be achieved by extending the global Query type in GraphQL.&lt;/p&gt;

&lt;p&gt;You create two queries in local.schema.graphql since you have already configured graphql-code-generator to generate TypesScript types from this file. Query getAllLocalMovies will return Movie objects from the Apollo cache, while getAllLocalMoviesReactiveVars will use reactive variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="c"&gt;# src/graphql/graphql-local-schema/local.schema.graphql&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;extend&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="c"&gt;# for Apollo cache query&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;getAllLocalMovies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt; 
        &lt;/span&gt;&lt;span class="c"&gt;# for reactive variables&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;getAllLocalMoviesReactiveVars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use these queries, you have to attach the @client decorator, telling Apollo-client to resolve them on the client side and prevent executing them against the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="c"&gt;# src/graphql/graphql-custom-backend/movie-local.graphql&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetAllLocalMovies&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;getAllLocalMovies&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;@client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="n"&gt;MovieInfo&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GetAllLocalMoviesReactiveVars&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;getAllLocalMoviesReactiveVars&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;@client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="n"&gt;MovieInfo&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, regenerate the TypeScript schema by &lt;code&gt;npm run generate-types&lt;/code&gt;, which will create executable &lt;code&gt;GetAllLocalMoviesReactiveVarsGQL&lt;/code&gt; and &lt;code&gt;GetAllLocalMoviesGQL&lt;/code&gt; API calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client Queries
&lt;/h3&gt;

&lt;p&gt;To update local application data using client queries, you must implement the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Inject private apollo: Apollo to the service or component for Apollo client cache reference&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a data type you want to save into the cache&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update query data by the writeQuery methods. Example: calling &lt;code&gt;this.apollo.client.cache.writeQuery({...})&lt;/code&gt;, which can be seen in MovieLocalService in the code snippet below, line 22, with the following arguments:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;a.) query - TypeScript constant that wraps the whole client-side query we want to update. By using graphql-code-generator, you define GraphQL queries in &lt;code&gt;{{name}}.graphql&lt;/code&gt; file and generate constants by the registered npm script npm run generate-types. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GetAllLocalMoviesDocument&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
    query GetAllLocalMovies {
        getAllLocalMovies @client {
            ...MovieInfo
        }
    }
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MovieInfoFragmentDoc&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;b.) data - An object where you set the properties to what __typename you want to change. In most cases, you are updating a Query type, and the second attribute is the name of the query, defined in &lt;code&gt;{{name}}.graphql&lt;/code&gt;, that returns data you want to overwrite. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&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="nl"&gt;__typename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;getAllLocalMovies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;movie&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;c.) id - Object’s identification key when you update only one specific object, optional parameter&lt;/p&gt;

&lt;p&gt;4.) Implementing merge and read functions in the InMemoryCache.Query, if you intend to add additional logic for updating or reading client queries&lt;/p&gt;

&lt;p&gt;Let’s take a look at the following code snippet on how you would create and store local Movie entities in the local getAllLocalMovies query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MovieLocalService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;..&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;apollo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Apollo&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;....&lt;/span&gt;

    &lt;span class="nf"&gt;onMovieAddToApolloCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;MovieInputCreate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;rightNow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="c1"&gt;// create object&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MovieInfoFragment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;__typename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Movie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rightNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// fake ID&lt;/span&gt;
            &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rightNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rightNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="na"&gt;isSelected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MovieSelectType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Unselected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// local only field&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="c1"&gt;// update cache&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apollo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetAllLocalMoviesDocument&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;__typename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;getAllLocalMovies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GetAllLocalMoviesDocument is a generated constant variable by graphql-code-generator from GetAllLocalMovies query defined in movie-local.graphql file. In the method onMovieAddToApolloCache(...) you create a new Movie object and save it into getAllLocalMovies array.&lt;/p&gt;

&lt;p&gt;However, by saving a new Movie into getAllLocalMovies array, it is possible to overwrite its already existing list of values with just a single object. To avoid losing the stored list of Movie values, implement merge and read functions in InMemoryCache, Query type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InMemoryCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;typePolicies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;getAllLocalMovies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nf"&gt;read&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;MovieInfoFragment&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&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;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="na"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MovieInfoFragment&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; 
                        &lt;span class="na"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MovieInfoFragment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;MovieInfoFragment&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="c1"&gt;// if array is passed, rewrite already saved movies&lt;/span&gt;
                        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;incoming&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;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;As mentioned previously read(...) function is executed when getAllLocalMovies query is called. The initial read(...) execution would return undefined because no data had yet been saved into the cache, so instead, we return an empty array. &lt;/p&gt;

&lt;p&gt;Function merge(...) is executed when you write something into getAllLocalMovies array in Apollo cache, like in the previous code snippet by getAllLocalMovies: movie, where you instruct Apollo cache to store the newly created movie object alongside the already stored ones.&lt;/p&gt;

&lt;p&gt;Working with client queries can be tedious. You have to update Apollo cache by writeQuery, using the right query document and in its data change the correct field, and also implement merge(...) and read(...) functions. On the other hand, its major benefit is the ability to inspect the local state by Apollo Client Devtools and the option of adopting libraries such as &lt;a href="https://www.npmjs.com/package/apollo-cache-persist" rel="noopener noreferrer"&gt;Apollo-cache-persist&lt;/a&gt; to persist the cache state in client-side storage on application reload.&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%2F3wivrlskz32hwqlhtsui.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%2F3wivrlskz32hwqlhtsui.png" alt="Image description" width="693" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Reactive variables
&lt;/h3&gt;

&lt;p&gt;When you don’t care about storing the application’s local state in the Apollo cache, you can adopt the &lt;a href="https://www.apollographql.com/docs/react/local-state/reactive-variables/" rel="noopener noreferrer"&gt;reactive variables&lt;/a&gt; approach. Create a reactive variable with the &lt;code&gt;makeVar&amp;lt;T&amp;gt;()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;localMoviesReactiveVars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;makeVar&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MovieInfoFragment&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have already generated a getAllLocalMoviesReactiveVars query from movie-local.graphql, so you also have to tell Apollo’s InMemoryCache how to perform the read() operation on this query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InMemoryCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;typePolicies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;Movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="p"&gt;...&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;queryType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;getAllLocalMoviesReactiveVars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;localMoviesReactiveVars&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                        &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="na"&gt;getAllLocalMovies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="p"&gt;...&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;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;Use getAllLocalMoviesReactiveVars generated query in MovieLocalService, to return data from localMoviesReactiveVars() reactive variable or push data into it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MovieLocalService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;getAllLocalMoviesReactiveVarsGQL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GetAllLocalMoviesReactiveVarsGQL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="c1"&gt;// get current state of reactive variable&lt;/span&gt;
    &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;allLocalMoviesReactiveVars&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;MovieInfoFragment&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;localMoviesReactiveVars&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// subscribe on state change&lt;/span&gt;
    &lt;span class="nf"&gt;getAllLocalMoviesReactiveVars&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MovieInfoFragment&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAllLocalMoviesReactiveVarsGQL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueChanges&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&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;res&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;getAllLocalMoviesReactiveVars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// add new Movie to reactive variables&lt;/span&gt;
    &lt;span class="nf"&gt;onMovieAddToReactiveVariables&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;MovieInputCreate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;rightNow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MovieInfoFragment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;__typename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Movie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rightNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// fake ID&lt;/span&gt;
            &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rightNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rightNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="na"&gt;isSelected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MovieSelectType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Unselected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="c1"&gt;// save movie to reactive variables&lt;/span&gt;
        &lt;span class="nf"&gt;localMoviesReactiveVars&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;localMoviesReactiveVars&lt;/span&gt;&lt;span class="p"&gt;()]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;....&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As an Angular developer, you may be asking, what is the difference between reactive variables provided by Apollo client compared to &lt;a href="https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject" rel="noopener noreferrer"&gt;RxJs BehaviorSubject&lt;/a&gt;? Honestly, not much. Using reactive variables, you lose the option to inspect your local state in the Apollo cache with Apollo client devtools, compared to client-side queries. In the end, reactive variables and BehaviorSubjects behave the same way, and you lose debugging opportunities.&lt;/p&gt;

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

&lt;p&gt;Apollo client can be a valuable tool to cache client-side data without bringing additional external libraries into the picture. In this example, you learned how to extend the server-side schema with a local-only field and two ways to store local data with the help of the Apollo client library.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>graphql</category>
      <category>programming</category>
    </item>
    <item>
      <title>Angular v15 Directive Composition API</title>
      <dc:creator>Eduard Krivanek</dc:creator>
      <pubDate>Thu, 17 Nov 2022 07:44:45 +0000</pubDate>
      <link>https://dev.to/bitovi/angular-v15-directive-composition-api-28an</link>
      <guid>https://dev.to/bitovi/angular-v15-directive-composition-api-28an</guid>
      <description>&lt;p&gt;One of the advantages of using the &lt;a href="https://www.bitovi.com/frontend-javascript-consulting/angular-consulting" rel="noopener noreferrer"&gt;Angular&lt;/a&gt; ecosystem is that it never forgets about you. If Angular can’t solve your request right away because the current technology doesn’t allow it, they often return to it. An example of this is &lt;a href="https://github.com/angular/angular/issues/8785" rel="noopener noreferrer"&gt;issue #8785&lt;/a&gt;, which was open for 6 years but was finally solved in 2022.&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%2F4cec6f80b25srcj7gga8.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%2F4cec6f80b25srcj7gga8.png" alt="Image description" width="620" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Inheritance
&lt;/h2&gt;

&lt;p&gt;Some developers like to work smarter, not harder. They like to define some logic once, create a function only in one place and reuse it everywhere, following the principle of &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="noopener noreferrer"&gt;don’t repeat yourself&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;When having multiple Angular elements (Components, Directives, Pipes) that share the same logic, it is common to abstract that logic into a parent class and extend the parent using Inheritance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ParentCalculation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;calculation1&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="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// restricted only for Components&lt;/span&gt;
    &lt;span class="nf"&gt;calculation2&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="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ---------------------------------------&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-component1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
        &amp;lt;button (click)="calculation1()"&amp;gt;calculation1&amp;lt;/button&amp;gt;
        &amp;lt;button (click)="calculation2()"&amp;gt;calculation2&amp;lt;/button&amp;gt;
    `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Component1&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ParentCalculation&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ---------------------------------------&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Pipe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-pipe1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pipe1&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ParentCalculation&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;PipeTransform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;transform&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="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calculation1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inheritance works… Until it doesn’t. Let’s demonstrate the following problem: What if the method &lt;code&gt;calculation2&lt;/code&gt; inside the &lt;code&gt;ParentCalculation&lt;/code&gt; class would be restricted only to be executed for Components and not for Pipes?&lt;/p&gt;

&lt;p&gt;What if many more components would extend the &lt;code&gt;ParentCalculation&lt;/code&gt; class, and we realize we will need to add an additional &lt;code&gt;calculation3&lt;/code&gt; method because we, once again, have a repeated logic across multiple places that would be great to abstract? &lt;/p&gt;

&lt;p&gt;Abstracting a common logic into the &lt;code&gt;ParentCalculation&lt;/code&gt; could be a good idea. Still, we would expose unused methods (&lt;code&gt;calculation2&lt;/code&gt; and &lt;code&gt;calculation3&lt;/code&gt;) to every child class (Component, Pipe, Directive) even if they don’t need to or can’t use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter JavaScript Composition
&lt;/h2&gt;

&lt;p&gt;Composition is a design pattern to &lt;a href="https://www.geeksforgeeks.org/favoring-composition-over-inheritance-in-java-with-examples/" rel="noopener noreferrer"&gt;implement a &lt;strong&gt;has-a&lt;/strong&gt; relationship&lt;/a&gt;. To achieve this, you can use an instance variable that refers to other objects. The main benefits of compositions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Composition allows changing the behavior at runtime as long as the composed object implements the correct behavior&lt;/li&gt;
&lt;li&gt;It Decouples the dependency on the parent class, so if the parent behavior changes, it will not break the child component execution.&lt;/li&gt;
&lt;li&gt;It makes testing less complex because we have to mock Objects, not actual dependency classes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An example of Composition is the following code snippet&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Human&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Human&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;salary&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;human&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Human&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Human&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;human&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;salary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Romero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;employee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Composition API in Angular
&lt;/h2&gt;

&lt;p&gt;Composition sounds interesting in theory, but you might wonder how we can use it in Angular. Let me introduce you to a new composition API directive called &lt;a href="https://angular.io/guide/directive-composition-api" rel="noopener noreferrer"&gt;hostDirective&lt;/a&gt;, available in Angular v15. &lt;/p&gt;

&lt;p&gt;Composition allows composing functionalities from multiple standalone Directives into a more complex Directive or Component. Let me demonstrate it in the following snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[appClickLogging]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ButtonDirective&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;HostBinding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;attr.data-button-type&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="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&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="nd"&gt;HostListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`%c [Log]: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color: #3f51b5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// directive for all primary mat-button&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button[color="primary"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hostDirectives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ButtonDirective&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ButtonPrimaryDirective&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;buttonDirective&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ButtonDirective&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;buttonDirective&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ButtonDirective&lt;/code&gt; we created using Angular’s &lt;code&gt;@HostListener('click')&lt;/code&gt; is console logging each click event inside the &lt;code&gt;onClick&lt;/code&gt; method. It is a standard Angular Directive used in the following approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;appClickLogging&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"success"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Logging Success button
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s consider a scenario where a product manager asks us to track every &lt;code&gt;primary button&lt;/code&gt; click.&lt;/p&gt;

&lt;p&gt;Instead of manually attaching the &lt;code&gt;appClickLogging&lt;/code&gt; to all &lt;code&gt;primary buttons&lt;/code&gt;, we can create a &lt;code&gt;ButtonPrimaryDirective&lt;/code&gt; with a &lt;code&gt;button[color="primary"]&lt;/code&gt; selector to select all &lt;code&gt;&amp;lt;button mat-flat-button color="primary"&amp;gt;button&amp;lt;/button&amp;gt;&lt;/code&gt; buttons. And, using Composition, attach the directive that already implements the logging mechanism inside the &lt;code&gt;hostDirectives&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Attaching the &lt;code&gt;ButtonDirective&lt;/code&gt; class into a &lt;code&gt;hostDirectives&lt;/code&gt;, we can get a reference to that class inside our child component constructor by using &lt;a href="https://angular.io/guide/dependency-injection" rel="noopener noreferrer"&gt;dependency injection&lt;/a&gt; like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;buttonDirective&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ButtonDirective&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;@Host&lt;/code&gt; is optional but helps Angular resolve dependencies. Learn more about &lt;a href="https://angular.io/guide/hierarchical-dependency-injection#resolution-modifiers" rel="noopener noreferrer"&gt;resolution modifiers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Logging steps for some specific button is quite a common use case when we, for example, want to track how the user navigates through our page to find out how our application is being used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Angular Implementation of hostDirectives
&lt;/h2&gt;

&lt;p&gt;Opening the source of the &lt;code&gt;hostDirectives&lt;/code&gt; implementation, we can inspect that we can pass a class, &lt;code&gt;Type&amp;lt;unknown&amp;gt;&lt;/code&gt;, into the &lt;code&gt;hostDirectives&lt;/code&gt; or an object and specify &lt;code&gt;inputs&lt;/code&gt; and &lt;code&gt;outputs&lt;/code&gt; properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Code snippet from Angular source&lt;/span&gt;
&lt;span class="cm"&gt;/**
  * Standalone directives that should be applied to the 
  * host whenever the directive is matched.
  * By default none of the inputs or outputs of the 
  * host directives will be available on the host,
  * unless they are specified 
  * in the `inputs` or `outputs` properties.
  */&lt;/span&gt;
&lt;span class="nx"&gt;hostDirectives&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;directive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nl"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&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;Let’s look at an example of how to use &lt;code&gt;inputs&lt;/code&gt; and &lt;code&gt;outputs&lt;/code&gt; properties for the &lt;code&gt;hostDirectives&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[appClickLogging]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ButtonDirective&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;clickedEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&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="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;mouseEnterEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&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="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;loggingName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Base&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="nd"&gt;HostBinding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;attr.data-button-type&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="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;default&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="nd"&gt;HostListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clickedEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;HostListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mouseenter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;onMouseenter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mouseEnterEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ---------------------------------------------&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[appClickLoggingEnhanced]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hostDirectives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;directive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ButtonDirective&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loggingName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- inputs&lt;/span&gt;
            &lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mouseEnterEvent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- outputs&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ButtonDirectiveEnhancedDirective&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;buttonDirective&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ButtonDirective&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;buttonDirective&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ---------------------------------------------&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
        &amp;lt;button appClickLoggingEnhanced 
                (mouseEnterEvent)="onMouseEnterEvent()" 
                [loggingName]="testName"&amp;gt;
            Button text
        &amp;lt;/button&amp;gt;
    `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ButtonDirectiveEnhancedDirective&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;testName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;onMouseEnterEvent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[TestComponent]: mouse enter&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;What &lt;code&gt;inputs&lt;/code&gt; and &lt;code&gt;outputs&lt;/code&gt; properties allow is to define which properties from the composite &lt;code&gt;@Directive&lt;/code&gt; class are allowed to be exposed by the parent directive.&lt;/p&gt;

&lt;p&gt;In our case, &lt;code&gt;ButtonDirective&lt;/code&gt; has two inputs and two outputs, and it works as a normal directive. However, we need to tell &lt;code&gt;ButtonDirectiveEnhancedDirective&lt;/code&gt; which properties it can expose from the &lt;code&gt;ButtonDirective&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Exposing &lt;code&gt;loggingName&lt;/code&gt; from &lt;code&gt;ButtonDirectiveEnhancedDirective&lt;/code&gt; allows defining the &lt;code&gt;@Input()&lt;/code&gt; in &lt;code&gt;TestComponent&lt;/code&gt;. If the &lt;code&gt;loggingName&lt;/code&gt; was removed from inputs in &lt;code&gt;ButtonDirectiveEnhancedDirective&lt;/code&gt;, the compiler would throw the following error.&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%2Fosza4xev6xocxxbchgf6.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%2Fosza4xev6xocxxbchgf6.png" alt="Image description" width="800" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Angular Composition API restrictions
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; Remember the following. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can use &lt;code&gt;hostDirectives&lt;/code&gt; in both Components and Directives&lt;/li&gt;
&lt;li&gt;Classes in &lt;code&gt;hostDirectives&lt;/code&gt; must be decorated with &lt;code&gt;@Directive&lt;/code&gt; decorator&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;hostDirectives&lt;/code&gt; directive can be used only for &lt;a href="https://angular.io/guide/standalone-components" rel="noopener noreferrer"&gt;standalone components&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;inputs&lt;/code&gt; and &lt;code&gt;outputs&lt;/code&gt; to expose properties from the composed &lt;code&gt;hostDirectives&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Accessing the composed directive instance inside the &lt;code&gt;constructor&lt;/code&gt;, like &lt;code&gt;constructor(buttonDirective: ButtonDirective)&lt;/code&gt;, without including it into &lt;code&gt;hostDirectives&lt;/code&gt;, would result in an error message &lt;strong&gt;No provider for ButtonDirective found in NodeInjector&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/angular/angular/pull/46868" rel="noopener noreferrer"&gt;proposed PR&lt;/a&gt; and the massive &lt;a href="https://github.com/angular/angular/commit/54ceed53e21a6a899617b626becc51ffb1059178" rel="noopener noreferrer"&gt;code implementation&lt;/a&gt; to find out more about implementing the hostDirectives support for the Angular compiler.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composition API Examples
&lt;/h2&gt;

&lt;p&gt;Using Composition in Angular instead of Inheritance may be a little bit difficult to wrap your head around. You may not instantly come up with use cases for how to use the new &lt;code&gt;hostDirectives&lt;/code&gt; directive, so let me demonstrate its purpose in the following examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example 1
&lt;/h3&gt;

&lt;p&gt;We have created a &lt;code&gt;TypingTrackingDirective&lt;/code&gt; directive, that by attaching it to any input element will log out the user’s input. We are asked to add this implementation to all &lt;code&gt;textarea&lt;/code&gt; inputs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;appTypingTracking&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TypingTrackingDirective&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;HostListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;focus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$event.target.value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;onFocus&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;HostListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$event.target.value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;onInput&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Tracking input: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;textarea&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hostDirectives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;TypingTrackingDirective&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InputTrackingDirective&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 2
&lt;/h3&gt;

&lt;p&gt;A common practice is to use &lt;a href="https://rxjs.dev/api/operators/takeUntil" rel="noopener noreferrer"&gt;takeUntil RxJS operator&lt;/a&gt; with some Subject when subscribing to an Observable. This logic is repeated in multiple places, so let’s abstract it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Credits: &lt;/span&gt;
&lt;span class="c1"&gt;// https://twitter.com/_crisbeto/status/1582475442715385858&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DestroyDirective&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnDestroy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;destroy$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&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;get&lt;/span&gt; &lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;takeUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destroy$&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;ngOnDestroy&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destroy$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destroy$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ApiService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DestroyDirective&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompositionNewComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;untilDestroyed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DestroyDirective&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;apiService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApiService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;linstenToUserWS&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;untilDestroyed&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 3
&lt;/h3&gt;

&lt;p&gt;We want to extend the behavior of the &lt;code&gt;*ngIf&lt;/code&gt; directive so that we are able to reveal HTML content when an HTTP request has finished, but we can also toggle its visibility by clicking on a button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActiveService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;active$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asObservable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;toggleActivation&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Toggling state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[ifActive]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hostDirectives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;NgIf&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActiveDirective&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;ngIfDirective&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;NgIf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;activeService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ActiveService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activeService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ngIfDirective&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ngIf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[toggleActive]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ToggleActiveDirective&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SkipSelf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;activeService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ActiveService&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;HostListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activeService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleActivation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;!-- using ngIfActive directive --&amp;gt;
    &amp;lt;button toggleActive&amp;gt;Toggle Reveal&amp;lt;/button&amp;gt;

    &amp;lt;!-- display 2 revealing block --&amp;gt;
    &amp;lt;div *ifActive&amp;gt;Toggling state 1111&amp;lt;/div&amp;gt;
    &amp;lt;div *ifActive&amp;gt;Toggling state 2222&amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ToggleActiveDirective&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ActiveDirective&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ActiveService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;activeService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ActiveService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// mocking HTTP request -&amp;gt; reveal content after 3 seconds&lt;/span&gt;
        &lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activeService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggleActivation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
             &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example 4
&lt;/h3&gt;

&lt;p&gt;Let’s say we are using &lt;code&gt;CdkDrag&lt;/code&gt; and &lt;code&gt;matTooltip&lt;/code&gt; plenty of times in our application by the following approach&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;cdkDrag&lt;/span&gt; &lt;span class="na"&gt;matTooltip=&lt;/span&gt;&lt;span class="s"&gt;"Info"&lt;/span&gt; &lt;span class="na"&gt;[matTooltipHideDelay]=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Click me
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To compose the behavior of these two Directives, you may be tempted to create something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[appButtonTooltip]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;standalone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hostDirectives&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;directive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MatTooltip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
               &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;matTooltip: tooltip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;matTooltipHideDelay: tooltipHideDelay&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;directive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CdkDrag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ButtonTooltipDirective&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, this will not work. The Angular compiler will throw an error because as we previously mentioned you can only use Directives in &lt;code&gt;hostDirectives&lt;/code&gt; in Standalone Components.&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%2F57guxvatum7qg41gn4q8.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%2F57guxvatum7qg41gn4q8.png" alt="Image description" width="800" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Until Angular Material Directives do not migrate to standalone Directives, you have to use the old approach: &lt;code&gt;&amp;lt;button cdkDrag matTooltip="Info" [matTooltipHideDelay]="400"&amp;gt;&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;It is good to see that the Angular team is focusing on expanding its ecosystem and bringing new features. In this article, we described the newly added hostDirectives directive, and how it can be useful for abstracting repeated logic into one place and avoiding using Inheritance. The source code that covers this example and additional features can be found in the following &lt;a href="https://github.com/krivanek06/example_projects/tree/main/angular_composition_api" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more information check out our &lt;a href="https://www.bitovi.com/academy/" rel="noopener noreferrer"&gt;training program&lt;/a&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  Waiting for Angular to fix your problem?
&lt;/h3&gt;

&lt;p&gt;Let us take a whack at it! Book your free &lt;a href="https://www.bitovi.com/frontend-javascript-consulting/angular-consulting" rel="noopener noreferrer"&gt;Angular consulting&lt;/a&gt; call to talk through your project with an expert.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Getting Started with RxJS: All You Need to Know About Observables</title>
      <dc:creator>Fábio Englert Moutinho</dc:creator>
      <pubDate>Wed, 16 Nov 2022 13:17:49 +0000</pubDate>
      <link>https://dev.to/bitovi/getting-started-with-rxjs-all-you-need-to-know-about-observables-4dk9</link>
      <guid>https://dev.to/bitovi/getting-started-with-rxjs-all-you-need-to-know-about-observables-4dk9</guid>
      <description>&lt;p&gt;&lt;a href="https://rxjs.dev/guide/overview"&gt;RxJS&lt;/a&gt; is a library that combines the Observer pattern—where Observables or Subjects notify Observers of state changes—with functional programming to handle data changes over time.&lt;/p&gt;

&lt;p&gt;When programming with RxJS, you are usually:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating Observables to subscribe later&lt;/li&gt;
&lt;li&gt;Creating new Observables by piping existing Observables&lt;/li&gt;
&lt;li&gt;Subscribing to Observables to get data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As &lt;a href="https://rxjs.dev/guide/overview"&gt;Observables are “the most basic building block of RxJS"&lt;/a&gt;, having a solid understanding of Observables is paramount to becoming proficient in RxJS.&lt;/p&gt;

&lt;p&gt;In this blog post, you’ll learn what an Observable is, the different types of Observables and how they are helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an Observable?
&lt;/h2&gt;

&lt;p&gt;In essence, Observables represent data (or a state) that changes over time. Observables have two critical methods you should know about: &lt;a href="https://rxjs.dev/api/index/class/Observable#subscribe"&gt;subscribe&lt;/a&gt; and &lt;a href="https://rxjs.dev/api/index/class/Observable#pipe"&gt;pipe&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observable.subscribe()
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;subscribe&lt;/code&gt; will start the execution of an Observable and provides a way to observe Observable emitted notifications by passing Observer handlers.&lt;/p&gt;

&lt;p&gt;The Observer argument of &lt;code&gt;subscribe&lt;/code&gt; allows you to react when the Observable emits a new value, errors, or completes through &lt;code&gt;next&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and &lt;code&gt;complete&lt;/code&gt; callbacks.&lt;/p&gt;

&lt;p&gt;Each subscription to an Observable will create a new execution of the Observable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// emit sequential numbers every second and console.log that number&lt;/span&gt;
&lt;span class="nf"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;error&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="na"&gt;complete&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="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// if you don't care about error or complete, you can pass only the next function:&lt;/span&gt;
&lt;span class="nf"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://stackblitz.com/edit/typescript-jdkctb?devToolsHeight=100&amp;amp;file=index.ts"&gt;Code Available on StackBlitz&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Observable.pipe()
&lt;/h3&gt;

&lt;p&gt;The sole reason the &lt;code&gt;pipe&lt;/code&gt; method exists is to improve readability.&lt;/p&gt;

&lt;p&gt;Without &lt;code&gt;pipe&lt;/code&gt;, composing Observable streams with operators would be a nightmare. &lt;a href="https://rxjs.dev/guide/operators"&gt;Operators&lt;/a&gt; are pure functions that take a source Observable and return a new Observable.&lt;/p&gt;

&lt;p&gt;Imagine writing the following code to compose an Observable Stream:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * 1. interval - emit sequential numbers every second
 * 2. map - multiply emitted values by 2
 * 3. map - emit a string `Result: ${x}`
 * 4. tap - log every emitted value
 */&lt;/span&gt;
&lt;span class="nf"&gt;tap&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))(&lt;/span&gt;
  &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Result: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;x&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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&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;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nf"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Albeit the code above is valid, the &lt;code&gt;pipe&lt;/code&gt; method is always preferred.&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;pipe&lt;/code&gt; method, the code becomes more readable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * 1. interval - emit sequential numbers every second
 * 2. map - multiply emitted values by 2
 * 3. map - emit a string `Result: ${x}`
 * 4. tap - log every emitted value
 */&lt;/span&gt;
&lt;span class="nf"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&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;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
     &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Result: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://stackblitz.com/edit/typescript-eqws53?devToolsHeight=100&amp;amp;file=index.ts"&gt;Code Available on StackBlitz&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Subject?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://rxjs.dev/api/index/class/Subject"&gt;Subject&lt;/a&gt; class extends the Observable class to allow multicasting emissions to all Observers - in other words: each new subscription to a Subject will not create a new execution of the Subject.&lt;/p&gt;

&lt;p&gt;Subjects keep track of all their Observers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subject.next(), Subject.error() and Subject.complete()
&lt;/h3&gt;

&lt;p&gt;A Subject's &lt;code&gt;next&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and &lt;code&gt;complete&lt;/code&gt; methods will call all of its &lt;a href="https://rxjs.dev/guide/observer"&gt;Observers&lt;/a&gt;' &lt;code&gt;next&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and &lt;code&gt;complete&lt;/code&gt; methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mySubject1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Subject&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;mySubject2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;mySubject1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Subject 1 Next: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Subject 1 Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;mySubject1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A Value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;mySubject1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Something bad happened&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;mySubject2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Subject 2 Next: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Subject 2 Complete`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;mySubject2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://stackblitz.com/edit/typescript-fbsnht?devToolsHeight=100&amp;amp;file=index.ts"&gt;Code Available on StackBlitz&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Subject.asObservable()
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;asObservable&lt;/code&gt; method is useful when you want to hide the Subject’s methods when exposing it to consumers that should only use it as an Observable.&lt;/p&gt;

&lt;p&gt;For example, you might expose the Subject in a service as an Observable, so components using that service will not be able to call the next method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// MyService file&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mySubject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyType&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;public&lt;/span&gt; &lt;span class="nf"&gt;getSubject&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyType&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mySubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;asObservable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// MyComponent file&lt;/span&gt;
&lt;span class="nx"&gt;myService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSubject&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// Property 'next' does not exist on type 'Observable&amp;lt;MyType&amp;gt;'.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What is a BehaviorSubject?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;constructor(value: T)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rxjs.dev/api/index/class/BehaviorSubject"&gt;BehaviorSubject&lt;/a&gt; extends Subject to ensure late subscribers are notified with the latest emitted value.&lt;/p&gt;

&lt;p&gt;A BehaviorSubject differs from a Subject in two ways.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;BehaviorSubject requires an initial value passed in its constructor&lt;/li&gt;
&lt;li&gt;Observers will receive the latest emitted value when they subscribe to a BehaviorSubject
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myBehaviorSubject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Initial Value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;myBehaviorSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`First Subscription: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;myBehaviorSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Second Value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// a late subscription will receive the latest emitted value&lt;/span&gt;
&lt;span class="nx"&gt;myBehaviorSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&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="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Late Subscription: &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="s2"&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;a href="https://stackblitz.com/edit/typescript-zsa4xm?devToolsHeight=100&amp;amp;file=index.ts"&gt;Code Available on StackBlitz&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a ReplaySubject?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;constructor(_bufferSize: number = Infinity, _windowTime: number = Infinity, _timestampProvider: TimestampProvider = dateTimestampProvider)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rxjs.dev/api/index/class/ReplaySubject"&gt;ReplaySubject&lt;/a&gt; also extends Subject. ReplaySubject behaves similarly to BehaviorSubject but is capable of emitting multiple values when subscribed to.&lt;/p&gt;

&lt;p&gt;ReplaySubject differs from BehaviorSubject in three ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A ReplaySubject does not have an initial value.&lt;/li&gt;
&lt;li&gt;A ReplaySubject emits the last &lt;code&gt;bufferSize&lt;/code&gt; emissions when Observers subscribe to it. Values are held in a buffer for &lt;code&gt;windowTime&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A ReplaySubject still replays values for Observers even if it has been completed with an error.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myReplaySubject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ReplaySubject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&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="nx"&gt;myReplaySubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ReplaySubject Next: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ReplaySubject Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&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="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ReplaySubject Complete`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;myReplaySubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&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="nx"&gt;myReplaySubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&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="nx"&gt;myReplaySubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&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="nx"&gt;myReplaySubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Something bad happened&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// late subscription&lt;/span&gt;
&lt;span class="nx"&gt;myReplaySubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ReplaySubject Next: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ReplaySubject Error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&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="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`ReplaySubject Complete`&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;a href="https://stackblitz.com/edit/typescript-squcej?devToolsHeight=100&amp;amp;file=index.ts"&gt;Code Available on StackBlitz&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an AsyncSubject?
&lt;/h2&gt;

&lt;p&gt;An &lt;a href="https://rxjs.dev/api/index/class/AsyncSubject"&gt;AsyncSubject&lt;/a&gt; only emits the last value to its Observers when it completes. That’s it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myAsyncSubject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AsyncSubject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;myAsyncSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`AsyncSubject Next: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`AsyncSubject Complete`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;myAsyncSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;First Value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;myAsyncSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Second Value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;myAsyncSubject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://stackblitz.com/edit/typescript-pmcdtd?devToolsHeight=100&amp;amp;file=index.ts"&gt;Code Available on StackBlitz&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  On The Road to Mastering RxJS
&lt;/h2&gt;

&lt;p&gt;Now that you know how to use all the Observable Types—Observable, Subject, BehaviorSubject, ReplaySubject, and AsyncSubject—we highly recommend taking a look at the &lt;a href="https://rxjs.dev/guide/operators#categories-of-operators"&gt;operators' list in the official RxJS documentation&lt;/a&gt;, so you are at least exposed to most operators and know there’s a solution to every problem you are ever going to face.&lt;/p&gt;

&lt;p&gt;Finally, Bitovi offers a &lt;a href="https://www.bitovi.com/academy/learn-rxjs.html?hsLang=en-us"&gt;free RxJS course&lt;/a&gt; with great introductory and advanced content. You don't want to miss it. 👀&lt;/p&gt;

&lt;h3&gt;
  
  
  Are Subjects a tricky subject for you?
&lt;/h3&gt;

&lt;p&gt;Bitovi has expert &lt;a href="https://www.bitovi.com/frontend-javascript-consulting/angular-consulting"&gt;Angular consultants&lt;/a&gt; ready to help you tackle your most challenging RxJS questions. Schedule your free consultation today!&lt;/p&gt;

</description>
      <category>rxjs</category>
      <category>beginners</category>
      <category>angular</category>
    </item>
  </channel>
</rss>
