<?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: Isabelle M.</title>
    <description>The latest articles on DEV Community by Isabelle M. (@trinityyi).</description>
    <link>https://dev.to/trinityyi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F285617%2F7e814576-62c0-409c-970d-318a30520bc3.jpg</url>
      <title>DEV Community: Isabelle M.</title>
      <link>https://dev.to/trinityyi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/trinityyi"/>
    <language>en</language>
    <item>
      <title>Can We Ever Achieve a Utopian Release?</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Fri, 03 Apr 2026 20:03:50 +0000</pubDate>
      <link>https://dev.to/trinityyi/can-we-ever-achieve-a-utopian-release-ggf</link>
      <guid>https://dev.to/trinityyi/can-we-ever-achieve-a-utopian-release-ggf</guid>
      <description>&lt;p&gt;What if releases didn't feel stressful?&lt;/p&gt;

&lt;p&gt;Not just "we followed the process" safe, but actually safe. The kind where you don't hesitate before deploying, don't keep checking Slack afterward, and don't quietly wonder what might go wrong this time.&lt;/p&gt;

&lt;p&gt;Because if we're honest, most of us recognize a very specific moment.&lt;/p&gt;

&lt;p&gt;A release finishes. Everything is deployed.&lt;br&gt;
Dashboards are open. People are watching.&lt;/p&gt;

&lt;p&gt;Slack goes a bit quieter than usual.&lt;/p&gt;

&lt;p&gt;No one says anything, but the same thought is there in the background:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let's see what breaks.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;We spend a lot of time trying to improve releases.&lt;/p&gt;

&lt;p&gt;We add better pipelines. We introduce more automation. We create more environments.&lt;/p&gt;

&lt;p&gt;On paper, things look more mature over time.&lt;br&gt;
And yet, the feeling often doesn't change.&lt;/p&gt;

&lt;p&gt;That's because the real issue is not only technical.&lt;/p&gt;

&lt;p&gt;Releases don't feel risky because they fail. They feel risky because they are unpredictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Myth of the "Perfect Release"
&lt;/h2&gt;

&lt;p&gt;There is a quiet assumption behind many teams: If everything is done correctly, nothing will go wrong.&lt;/p&gt;

&lt;p&gt;It sounds reasonable. It's also not true.&lt;/p&gt;

&lt;p&gt;Systems are complex. Dependencies are not always visible. Production behaves differently. And people make decisions under pressure.&lt;/p&gt;

&lt;p&gt;You don't get perfect releases. You get managed risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Things Actually Go Wrong
&lt;/h2&gt;

&lt;p&gt;Most issues don't come from the places we expect.&lt;br&gt;
They come from small decisions that feel harmless:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"It's a small change"&lt;/li&gt;
&lt;li&gt;"Let's include this one as well"&lt;/li&gt;
&lt;li&gt;"We don’t need to wait for this"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each decision makes sense on its own. But they don't exist in isolation.&lt;br&gt;
Over time, they accumulate. And the system becomes harder to reason about.&lt;/p&gt;

&lt;p&gt;That's when releases start to feel risky.&lt;/p&gt;




&lt;p&gt;Most teams try to solve this with process and tooling.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They define what "done" means.&lt;/li&gt;
&lt;li&gt;They rely on automation.&lt;/li&gt;
&lt;li&gt;They introduce canary releases.&lt;/li&gt;
&lt;li&gt;They build dashboards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And all of these help. But they also create a dangerous illusion: That if everything looks correct, everything &lt;em&gt;is&lt;/em&gt; correct.&lt;/p&gt;

&lt;p&gt;In reality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A ticket can be "done" and still hide assumptions.&lt;/li&gt;
&lt;li&gt;Tests can pass and still miss real behavior.&lt;/li&gt;
&lt;li&gt;A canary can look healthy at 5% and fail at scale.&lt;/li&gt;
&lt;li&gt;Dashboards can show green while something important is broken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Release problems rarely come from one big mistake. They come from many small ones.&lt;/p&gt;

&lt;p&gt;One extra ticket.&lt;br&gt;
One skipped validation.&lt;br&gt;
One assumption left unchecked.&lt;/p&gt;

&lt;p&gt;Each decision feels reasonable. Together, they create unpredictability.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Helps
&lt;/h2&gt;

&lt;p&gt;There's no single fix.&lt;br&gt;
What works is consistency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only shipping work that is truly ready&lt;/li&gt;
&lt;li&gt;Introducing changes in small steps&lt;/li&gt;
&lt;li&gt;Detecting issues early&lt;/li&gt;
&lt;li&gt;Recovering quickly and calmly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are simple ideas. But they require discipline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Takeaways
&lt;/h2&gt;

&lt;p&gt;If you want to improve your releases, start here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define what "release-ready" actually means — and stick to it&lt;/li&gt;
&lt;li&gt;Reduce how much you ship at once&lt;/li&gt;
&lt;li&gt;Keep your main branch releasable at all times&lt;/li&gt;
&lt;li&gt;Monitor a few critical user flows closely after deployment&lt;/li&gt;
&lt;li&gt;Make rollback simple and familiar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't need to fix everything at once.&lt;br&gt;
Even one improvement can make releases feel more predictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thought
&lt;/h2&gt;

&lt;p&gt;A utopian release is not one where nothing ever goes wrong.&lt;br&gt;
It's one where things can go wrong — and it doesn't turn into chaos.&lt;br&gt;
Where issues are expected, visible, and manageable.&lt;br&gt;
Where releases stop feeling like events and start feeling like routine.&lt;/p&gt;

&lt;p&gt;The goal isn't perfect releases.&lt;br&gt;
It's releases you don’t have to be afraid of.&lt;/p&gt;

&lt;p&gt;That's probably the closest thing to utopia we get.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Docker vs. Kubernetes: Which Is Right for Your DevOps Pipeline?</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sat, 16 Nov 2024 14:05:10 +0000</pubDate>
      <link>https://dev.to/trinityyi/docker-vs-kubernetes-which-is-right-for-your-devops-pipeline-6h9</link>
      <guid>https://dev.to/trinityyi/docker-vs-kubernetes-which-is-right-for-your-devops-pipeline-6h9</guid>
      <description>&lt;p&gt;As modern applications grow in complexity, developers and DevOps teams face an important question: &lt;strong&gt;Docker or Kubernetes?&lt;/strong&gt; These two tools are foundational in the &lt;a href="https://en.wikipedia.org/wiki/DevOps" rel="noopener noreferrer"&gt;DevOps&lt;/a&gt; ecosystem, yet they serve distinct purposes based on the scale and requirements of your application pipeline.&lt;/p&gt;

&lt;p&gt;In this article, we'll break down their roles, address common myths, explore challenges, and provide practical guidance to help you decide which tool—or combination—is right for your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker and Kubernetes: Complementary Tools in DevOps
&lt;/h2&gt;

&lt;p&gt;Docker and Kubernetes are &lt;strong&gt;not competing tools&lt;/strong&gt; but complementary components in a modern DevOps workflow. Each serves a distinct role:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/strong&gt;: A containerization platform that simplifies packaging applications with dependencies into lightweight, portable containers. It’s indispensable for development, testing, and deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt;&lt;/strong&gt;: A container orchestrator that manages containers at scale, automating tasks like load balancing, scaling, and recovery, making it essential for production-ready applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: A developer might use Docker to create a container for a microservice and Kubernetes to deploy, scale, and monitor multiple instances of that container to handle user demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Addressing Common Misconceptions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Myth 1: You Must Choose Between Docker and Kubernetes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Reality&lt;/strong&gt;: Docker and Kubernetes often work together. Docker handles container creation, while Kubernetes orchestrates and scales them across clusters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: A development team might use Docker to package a microservice and Kubernetes to deploy and scale it across multiple servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Myth 2: Kubernetes Replaces Docker
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Reality&lt;/strong&gt;: Kubernetes builds on Docker (or another runtime) to manage clusters of containers. Think of Kubernetes as the conductor of an orchestra, with Docker playing the instruments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Myth 3: Kubernetes is Essential for Every Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Reality&lt;/strong&gt;: Kubernetes can be overkill for small-scale projects or single-container applications, where Docker alone may suffice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Myth 4: Docker Swarm and Kubernetes are Interchangeable
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Reality&lt;/strong&gt;: &lt;a href="https://docs.docker.com/engine/swarm/" rel="noopener noreferrer"&gt;Docker Swarm&lt;/a&gt; is simpler but lacks Kubernetes’ advanced features like self-healing and multi-cloud support. Swarm is best for small-scale projects, while Kubernetes excels in complex environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing Between Docker and Kubernetes for Your DevOps Pipeline
&lt;/h2&gt;

&lt;p&gt;Every DevOps pipeline consists of distinct stages, and Docker and Kubernetes each shine in different areas. Let’s explore their strengths across key workflows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Development, Local Testing, and Continuous Integration (CI)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Tool&lt;/strong&gt;: Docker
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt;: Docker simplifies creating lightweight, consistent environments that mirror production. Its isolated environments ensure reliable testing during development and CI pipelines, minimizing errors caused by mismatched configurations.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: A developer working on a microservice can spin up a Docker container with the exact dependencies needed for development and testing. In CI pipelines, containers allow each build to run in a consistent environment, preventing interference from other processes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro Tip&lt;/strong&gt;: Use &lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose&lt;/code&gt;&lt;/a&gt; to manage multiple containers locally, and integrate Docker with CI tools like &lt;a href="https://www.jenkins.io/" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt;, &lt;a href="https://github.com/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;, or &lt;a href="https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/" rel="noopener noreferrer"&gt;GitLab CI&lt;/a&gt; for seamless automation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Continuous Deployment (CD) and Production&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Tool&lt;/strong&gt;: Kubernetes
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt;: Kubernetes excels at managing complex production systems. Its ability to handle load balancing, automatic scaling, and container recovery ensures applications remain stable even under high traffic or unexpected failures.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: A high-traffic e-commerce platform uses Kubernetes to scale microservices during Black Friday sales automatically.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro Tip&lt;/strong&gt;: Use &lt;a href="https://helm.sh/" rel="noopener noreferrer"&gt;Helm charts&lt;/a&gt; to manage Kubernetes configurations and deployments more efficiently.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Multi-Cloud or Hybrid Environments&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Tool&lt;/strong&gt;: Kubernetes
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt;: Kubernetes provides a unified way to deploy and manage containers across multiple clouds or on-premise setups, ensuring seamless integration and consistent deployment experiences.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: A SaaS company deploying applications on both AWS and Google Cloud uses Kubernetes to ensure the same configurations are applied across regions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro Tip&lt;/strong&gt;: Use Kubernetes operators to extend its functionality for specific cloud services like &lt;a href="https://aws.amazon.com/rds/" rel="noopener noreferrer"&gt;AWS RDS&lt;/a&gt; or &lt;a href="https://cloud.google.com/bigquery" rel="noopener noreferrer"&gt;GCP BigQuery&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Monitoring and Observability&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Tool&lt;/strong&gt;: Kubernetes
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why&lt;/strong&gt;: Kubernetes integrates seamlessly with monitoring tools like &lt;a href="https://prometheus.io/" rel="noopener noreferrer"&gt;Prometheus&lt;/a&gt; and &lt;a href="https://grafana.com/" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt;, allowing teams to track resource usage, application performance, and potential bottlenecks.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: A team monitoring microservice performance uses Grafana dashboards to identify latency issues in real time.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro Tip&lt;/strong&gt;: Set up alerts in Prometheus for automated issue detection and faster response times.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Alternatives to Docker and Kubernetes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Alternatives to Docker:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://podman.io/" rel="noopener noreferrer"&gt;Podman&lt;/a&gt;&lt;/strong&gt;: Rootless and daemonless, offering enhanced security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://linuxcontainers.org/" rel="noopener noreferrer"&gt;LXC (Linux Containers)&lt;/a&gt;&lt;/strong&gt;: Lightweight containerization for simpler use cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Alternatives to Kubernetes:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://docs.docker.com/engine/swarm/" rel="noopener noreferrer"&gt;Docker Swarm&lt;/a&gt;&lt;/strong&gt;: Simpler orchestration for small projects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.nomadproject.io/" rel="noopener noreferrer"&gt;Nomad&lt;/a&gt;&lt;/strong&gt;: Supports mixed workloads and integrates with HashiCorp tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.serverless.com/" rel="noopener noreferrer"&gt;Serverless Frameworks&lt;/a&gt;&lt;/strong&gt;: Event-driven platforms like AWS Lambda for lightweight applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker vs. Kubernetes: Pros and Cons
&lt;/h2&gt;

&lt;p&gt;Here’s a quick comparison of their key features:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Docker&lt;/th&gt;
&lt;th&gt;Kubernetes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ease of Use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intuitive for local environments and testing.&lt;/td&gt;
&lt;td&gt;Requires orchestration and clustering knowledge but simplified by managed services.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ideal for single-host or small-scale applications.&lt;/td&gt;
&lt;td&gt;Built to handle distributed, large-scale applications.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resource Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Basic capabilities; scaling is manual.&lt;/td&gt;
&lt;td&gt;Advanced auto-scaling and scheduling.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fault Tolerance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited failover capabilities.&lt;/td&gt;
&lt;td&gt;Robust self-healing and failover mechanisms.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quick setup for simple applications.&lt;/td&gt;
&lt;td&gt;Slower initial setup but efficient for complex deployments.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Minimal infrastructure requirements.&lt;/td&gt;
&lt;td&gt;Resource-intensive but can be optimized using cloud services.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Common Challenges and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Docker Challenges:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dependency Bloat&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Use multi-stage builds to reduce image size.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Risks&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Use trusted images and avoid running containers as root.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Kubernetes Challenges:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High Complexity&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Use managed services like GKE, EKS, or AKS to simplify cluster setup.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring Overload&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Implement tools like Prometheus and Grafana to track metrics and set alerts.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overhead for Small Projects&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Consider lighter tools like Docker Compose for simpler applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion: Finding the Right Tool for Your DevOps Needs
&lt;/h2&gt;

&lt;p&gt;Docker and Kubernetes are foundational to modern DevOps workflows. For small-scale workflows, Docker provides simplicity and efficiency. For distributed, high-traffic systems, Kubernetes offers unparalleled scalability and reliability.&lt;/p&gt;

&lt;p&gt;Remember, these tools often work together to create seamless pipelines. Start small, experiment, and scale your approach as your needs evolve.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>REST vs. GraphQL: Choosing the Right API for Your Project</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Thu, 14 Nov 2024 23:09:20 +0000</pubDate>
      <link>https://dev.to/trinityyi/rest-vs-graphql-choosing-the-right-api-for-your-project-12jm</link>
      <guid>https://dev.to/trinityyi/rest-vs-graphql-choosing-the-right-api-for-your-project-12jm</guid>
      <description>&lt;p&gt;In the world of APIs, REST and GraphQL are two popular choices, each offering unique advantages. Choosing the right approach can significantly impact the performance, flexibility, and scalability of your project. This article will explore the key differences between REST and GraphQL, providing insights to help you determine which is best suited for your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is REST?
&lt;/h2&gt;

&lt;p&gt;REST (Representational State Transfer) is an architectural style where clients interact with servers through specific endpoints and HTTP methods (like GET, POST, PUT, DELETE) to retrieve or modify data. Each REST endpoint represents a unique resource and returns standard HTTP status codes for handling errors and responses.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: REST is straightforward and predictable, making it easy to work with.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: REST endpoints suit caching well, improving performance in applications with repeated data requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  REST API Example: Fetching a User Profile
&lt;/h3&gt;

&lt;p&gt;In a REST API, you might retrieve a user's profile with a &lt;code&gt;GET&lt;/code&gt; request to an endpoint like &lt;code&gt;/users/123&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;GET&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;
&lt;span class="nx"&gt;Response&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;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;John Doe&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;email&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;john.doe@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;REST is effective for simpler applications where data relationships are minimal and caching is important. Its predictable structure suits straightforward CRUD applications and microservices.&lt;/p&gt;

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

&lt;p&gt;GraphQL, developed by Facebook, is a query language that lets clients define the exact data they need. Unlike REST, which requires multiple endpoints, GraphQL uses a single endpoint with flexible queries for specific fields, minimizing data transfer and enhancing efficiency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexible Data Retrieval&lt;/strong&gt;: Clients can request only the necessary data, reducing over-fetching and under-fetching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Endpoint&lt;/strong&gt;: With GraphQL, you use one endpoint, and clients specify the data structure they need.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GraphQL Example: Fetching a User Profile with Specific Fields
&lt;/h3&gt;

&lt;p&gt;In GraphQL, you can fetch only the fields you need by specifying them in the query. Here's how a request for a user's profile might look:&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;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="n"&gt;user&lt;/span&gt;&lt;span class="p"&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="s2"&gt;"123"&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="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;email&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;GraphQL is particularly beneficial in projects that require complex, nested data or real-time features. Its flexibility can significantly reduce data transfer, especially in mobile apps where network efficiency is crucial.&lt;/p&gt;

&lt;h2&gt;
  
  
  REST vs. GraphQL: Key Differences
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Flexibility&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;REST&lt;/strong&gt;: With predefined endpoints, REST can lead to over-fetching or under-fetching, especially if the client doesn't need all the data an endpoint provides.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GraphQL&lt;/strong&gt;: Clients specify only the data they need, which makes data fetching more efficient and reduces bandwidth usage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Suppose you need a user's posts along with the profile data. In REST, you might need a separate endpoint to fetch posts, resulting in multiple requests. With GraphQL, you can retrieve everything in one request:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&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="n"&gt;user&lt;/span&gt;&lt;span class="p"&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="s2"&gt;"123"&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="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="n"&gt;posts&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;title&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;content&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;API Structure&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;REST&lt;/strong&gt;: Uses multiple endpoints, each mapping to a specific resource (e.g., &lt;code&gt;/users&lt;/code&gt;, &lt;code&gt;/posts&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GraphQL&lt;/strong&gt;: Has a single endpoint that handles all requests, with clients specifying the data structure and fields they need.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;REST&lt;/strong&gt;: Works well with HTTP caching since each endpoint has a predictable structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GraphQL&lt;/strong&gt;: Caching is more complex due to the dynamic nature of requests. GraphQL often requires specific client tools, like Apollo Client, to manage client-side caching effectively.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;REST&lt;/strong&gt;: Uses standard HTTP status codes (e.g., 404, 500) for clear error handling, which is familiar to most developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GraphQL&lt;/strong&gt;: Errors are handled within the response body, so clients must parse responses to handle errors properly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  REST vs. GraphQL: Performance Considerations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;REST&lt;/strong&gt; can be faster for simpler applications due to HTTP caching and predictable, resource-specific endpoints. In cases with complex data requirements, however, &lt;strong&gt;GraphQL&lt;/strong&gt; can be more efficient because it enables clients to fetch precisely the data they need in a single request. This can reduce network round-trips, which is beneficial for performance in applications with nested data. At the same time, complex GraphQL queries can increase server load due to custom query processing, so it's essential to consider your application's data complexity, caching needs, and server capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative API Approaches
&lt;/h2&gt;

&lt;p&gt;While REST and GraphQL are popular, there are other API styles worth considering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;gRPC&lt;/strong&gt;: Great for high-performance, low-latency applications, especially in microservices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOAP&lt;/strong&gt;: Commonly used in enterprise applications with strict data validation and security needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These alternatives provide other design options if REST and GraphQL aren't the best fit for your specific requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use REST
&lt;/h2&gt;

&lt;p&gt;REST might be the best choice if your project requirements include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simple Data Structure&lt;/strong&gt;: When data doesn't require nested relationships, REST's straightforward nature fits well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardized API&lt;/strong&gt;: REST's use of HTTP codes makes it easy to understand and standardize, especially for public APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching Needs&lt;/strong&gt;: REST's endpoints are well-suited for caching, making it ideal for applications where caching is essential.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideal for&lt;/strong&gt;: Microservices, CRUD apps, and APIs with simpler, non-nested data structures.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use GraphQL
&lt;/h2&gt;

&lt;p&gt;Consider GraphQL if your project requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complex, Nested Data&lt;/strong&gt;: GraphQL's nested queries are efficient for data-heavy applications where multiple related data points are needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Data&lt;/strong&gt;: When clients need to fetch only specific fields, GraphQL is more efficient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Data&lt;/strong&gt;: GraphQL's subscriptions allow for real-time data updates, which can be essential for applications needing live updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideal for&lt;/strong&gt;: Mobile apps, real-time applications, and applications requiring highly flexible queries and efficient data fetching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actionable Checklist for Choosing REST vs. GraphQL
&lt;/h2&gt;

&lt;p&gt;To make your decision even easier, here's a quick checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use REST&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your data requirements are simple and flat.&lt;/li&gt;
&lt;li&gt;Caching is a high priority for your project.&lt;/li&gt;
&lt;li&gt;You want predictable endpoint structures for easier debugging.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Use GraphQL&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your application needs flexible, nested queries.&lt;/li&gt;
&lt;li&gt;Reducing data over-fetching is critical for performance.&lt;/li&gt;
&lt;li&gt;Real-time data updates are part of the application requirements.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;Both REST and GraphQL excel in different scenarios, and sometimes they can even complement each other within a project. REST is ideal for predictable data and caching needs, while GraphQL shines in applications requiring flexible queries and real-time updates.&lt;/p&gt;

&lt;p&gt;Here's a quick summary table to help you decide:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;REST&lt;/th&gt;
&lt;th&gt;GraphQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Data Flexibility&lt;/td&gt;
&lt;td&gt;May lead to over/under-fetching&lt;/td&gt;
&lt;td&gt;Highly flexible, request-specific fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Structure&lt;/td&gt;
&lt;td&gt;Multiple endpoints for resources&lt;/td&gt;
&lt;td&gt;Single endpoint with custom queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Caching&lt;/td&gt;
&lt;td&gt;Straightforward caching&lt;/td&gt;
&lt;td&gt;More complex, often needs client tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error Handling&lt;/td&gt;
&lt;td&gt;Uses HTTP status codes&lt;/td&gt;
&lt;td&gt;Errors are within the response body&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>webdev</category>
      <category>graphql</category>
      <category>rest</category>
      <category>api</category>
    </item>
    <item>
      <title>Understanding Git Branching in 5 Minutes</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sat, 02 Nov 2024 15:49:52 +0000</pubDate>
      <link>https://dev.to/trinityyi/understanding-git-branching-in-5-minutes-48bk</link>
      <guid>https://dev.to/trinityyi/understanding-git-branching-in-5-minutes-48bk</guid>
      <description>&lt;p&gt;&lt;strong&gt;Git branching&lt;/strong&gt; is an essential part of version control, allowing multiple people (or just you!) to work on features, fixes, and updates without disrupting the stable codebase. Understanding how to use branches in a project can help keep the workflow smooth and minimize conflicts. Here's a quick guide to Git branching basics.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Branch in Git?
&lt;/h2&gt;

&lt;p&gt;In Git, a branch is a separate line of development that lets you work independently of the main codebase. When you create a branch, it's a copy of &lt;code&gt;main&lt;/code&gt; (or &lt;code&gt;master&lt;/code&gt;) where you can safely make changes without affecting the stable code.&lt;br&gt;
Think of branches as different versions or "paths" of your project that can later be merged back together.&lt;/p&gt;
&lt;h2&gt;
  
  
  Working with Feature Branches in a Git Project
&lt;/h2&gt;

&lt;p&gt;In a Git project, it's best practice to create a new branch for each feature or fix, keeping changes organized and minimizing conflicts. Here's the typical workflow for working on a feature branch:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a Feature Branch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start by updating your local &lt;code&gt;main&lt;/code&gt; branch with the latest code:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main
git pull origin main
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Next, create and switch to a new branch for your feature, using a descriptive name like &lt;code&gt;feature-login-form&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature-login-form
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Keep Your Branch Up-to-Date&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As you work on your feature, other team members may make changes to &lt;code&gt;main&lt;/code&gt;. Regularly sync your feature branch with &lt;code&gt;main&lt;/code&gt; to avoid conflicts down the line:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout main
git pull origin main
git checkout feature-login-form
git rebase main
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;If your branch is only being used by you, &lt;strong&gt;rebasing&lt;/strong&gt; onto &lt;code&gt;main&lt;/code&gt; keeps your branch history clean and linear by replaying your commits on top of the latest &lt;code&gt;main&lt;/code&gt;. This minimizes conflicts during the final merge. However, if you're working on a shared branch, consider merging &lt;code&gt;main&lt;/code&gt; instead of rebasing to avoid rewriting history and disrupting collaborators.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Merging Your Feature Branch into &lt;code&gt;main&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When your feature is complete, push your branch to the remote repository:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin feature-login-form
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Merging vs. Rebasing: When to Use Each
&lt;/h2&gt;

&lt;p&gt;In a Git project, you have two main ways to integrate changes from one branch into another: merging and rebasing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Merging&lt;/strong&gt;: Keeps all original commits intact and adds a "merge commit" to combine branches. This approach is great for shared branches because it preserves the full commit history and is less disruptive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rebasing&lt;/strong&gt;: Replays your commits on top of the latest &lt;code&gt;main&lt;/code&gt; branch, creating a linear history without merge commits. It's ideal for keeping your branch history clean but should be done only on personal branches. &lt;strong&gt;Avoid rebasing environment branches or shared branches&lt;/strong&gt;, as it rewrites history and may disrupt other team members' work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short, merge when you need a quick update and rebase when you want a tidy, linear commit history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Branching
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Descriptive Branch Names:&lt;/strong&gt; Naming conventions (e.g., &lt;code&gt;feature-&lt;/code&gt;, &lt;code&gt;bugfix-&lt;/code&gt;, &lt;code&gt;hotfix-&lt;/code&gt;) make it easy to understand the purpose of each branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make Frequent, Focused Commits:&lt;/strong&gt; Small commits with meaningful messages help with tracking changes and identifying issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep Your Branch Up-to-Date with &lt;code&gt;main&lt;/code&gt;:&lt;/strong&gt; Regularly syncing with &lt;code&gt;main&lt;/code&gt; reduces conflicts during the final merge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Integration Branches for Complex Features:&lt;/strong&gt; For multi-person features, consider an integration branch to test combined changes before merging into &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Feature Flags for Incomplete Features:&lt;/strong&gt; Feature flags allow you to merge work early without exposing it to end users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git branching is a powerful tool that, when used effectively, helps teams manage complexity, avoid conflicts, and maintain a clean codebase. By following these branching strategies and best practices, you'll be well-prepared to handle both solo projects and collaborative work with confidence.&lt;/p&gt;

</description>
      <category>git</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>How to check if a tuple is empty in Python?</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sat, 24 Dec 2022 22:00:00 +0000</pubDate>
      <link>https://dev.to/trinityyi/how-to-check-if-a-tuple-is-empty-in-python-2ie2</link>
      <guid>https://dev.to/trinityyi/how-to-check-if-a-tuple-is-empty-in-python-2ie2</guid>
      <description>&lt;p&gt;Just like lists, tuples are also a sequence of values and are considered falsy if they are empty. So, if you want to check if a tuple is empty, you can simply use the &lt;code&gt;not&lt;/code&gt; operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;empty_tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;non_empty_tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;empty_tuple&lt;/span&gt; &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;non_empty_tuple&lt;/span&gt; &lt;span class="c1"&gt;# False
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code example, we can see that the &lt;code&gt;not&lt;/code&gt; operator returns &lt;code&gt;True&lt;/code&gt; if the tuple is empty and &lt;code&gt;False&lt;/code&gt; if the tuple is not empty. The &lt;code&gt;not&lt;/code&gt; operator is a unary operator that returns the opposite of the value it is applied to. Using the &lt;code&gt;not&lt;/code&gt; operator is considered the most Pythonic way to check if a object is empty.&lt;/p&gt;

&lt;p&gt;There are other ways to check if a tuple is empty. For example, you can use the &lt;code&gt;len()&lt;/code&gt; function. This function returns the length of the tuple, which is 0 if the tuple is empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;empty_tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;non_empty_tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;empty_tuple&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;non_empty_tuple&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;# False
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One more way to check if a tuple is empty is to compare the tuple to an empty tuple using the &lt;code&gt;==&lt;/code&gt; operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;empty_tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;non_empty_tuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;empty_tuple&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;span class="n"&gt;non_empty_tuple&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# False
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Javascript Array.from() second argument</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sun, 18 Dec 2022 10:00:00 +0000</pubDate>
      <link>https://dev.to/trinityyi/javascript-arrayfrom-second-argument-16b9</link>
      <guid>https://dev.to/trinityyi/javascript-arrayfrom-second-argument-16b9</guid>
      <description>&lt;p&gt;&lt;code&gt;Array.from()&lt;/code&gt; is a method that creates a new array from an array-like or iterable object. However, one property that is often overlooked is that the method can accept a mapping function as a second argument. &lt;/p&gt;

&lt;p&gt;This map function is called on every element of the array that is being generated. Basically, &lt;code&gt;Array.from()&lt;/code&gt; with a function as a second argument is equivalent to &lt;code&gt;Array.from().map()&lt;/code&gt; only that it does not create an intermediate array.&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&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="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;x&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="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// [2, 4, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One very simple use case for this is to create an array of a specific length and fill it with an arithmetic sequence. &lt;br&gt;
For example, if you want to create an array of 5 elements and fill it with the value 1 to 5, you can do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&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="nx"&gt;v&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="o"&gt;=&amp;gt;&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;1&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [1, 2, 3, 4, 5]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why do SQL Server views need refreshing?</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sun, 04 Dec 2022 10:00:00 +0000</pubDate>
      <link>https://dev.to/trinityyi/why-do-sql-server-views-need-refreshing-1e4j</link>
      <guid>https://dev.to/trinityyi/why-do-sql-server-views-need-refreshing-1e4j</guid>
      <description>&lt;p&gt;Views in SQL are a great way to simplify complex queries, to hide sensitive data, or to provide a different perspective on the data. But they can also be a source of confusion and frustration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do SQL Server views need refreshing?
&lt;/h2&gt;

&lt;p&gt;A view, basically, is a stored query represented as a virtual table. When you create a view, you can use it just like a table which means you can query it, join it, and use it in other queries. Basically, a view is a snapshot of the schema at the time it was created. &lt;br&gt;
However, if a schema change occurs which causes the underlying object to change, the metadata of the view will not be updated automatically and the results of the view will be incorrect. Note that the need to refresh a view depends on the underlying object. For example, if the underlying object is a view, a refresh may not be needed.&lt;/p&gt;

&lt;p&gt;Schema changes can be caused by a number of things, such as adding a new column to a table, changing the data type of a column, or even deleting a column. So basically if you have a view that references a table that has changed, you will need to refresh the view. &lt;/p&gt;
&lt;h2&gt;
  
  
  How to refresh a view
&lt;/h2&gt;

&lt;p&gt;There are a few ways to refresh a view. The  most common way is to use the &lt;code&gt;DROP VIEW&lt;/code&gt; and &lt;code&gt;CREATE VIEW&lt;/code&gt; statements. This will drop the view and then recreate it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;view_name&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;view_name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;column_name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple and effective solution, but it can be time-consuming if the view is complex. &lt;/p&gt;

&lt;p&gt;Another way is to use the stored procedure &lt;code&gt;sp_refreshview&lt;/code&gt; which is a system stored procedure available in SQL Server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;EXEC&lt;/span&gt; &lt;span class="n"&gt;sp_refreshview&lt;/span&gt; &lt;span class="s1"&gt;'view_name'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This stored procedure will refresh the view and update the metadata to match the base table.&lt;/p&gt;

&lt;p&gt;Finally, if the tables are all in the same database on the same server you can use the option &lt;code&gt;WITH SCHEMABINDING&lt;/code&gt; when creating the view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="n"&gt;view_name&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;SCHEMABINDING&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;column_name&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This option binds the view to the schema of the underlying table. This means that this base table cannot be modified in a way that would affect the view definition. The view definition itself must first be modified or dropped to remove dependencies on the table that is to be modified. &lt;/p&gt;

</description>
      <category>sql</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>When to use useRef() instead of useState()</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sat, 26 Nov 2022 22:00:00 +0000</pubDate>
      <link>https://dev.to/trinityyi/when-to-use-useref-instead-of-usestate-3h4o</link>
      <guid>https://dev.to/trinityyi/when-to-use-useref-instead-of-usestate-3h4o</guid>
      <description>&lt;p&gt;In React, hooks are a way to use state and other React features without having to generate a class component. One of the most frequently used hook is &lt;code&gt;useState()&lt;/code&gt;, however on occasion &lt;code&gt;useRef()&lt;/code&gt; might be a better and more efficient way to manage state. &lt;br&gt;
A common use case is handling a form input field when the submit button is clicked. For example, lets look at the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPassword&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;setPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&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;In the above example, we have two input fields, one for the email and one for the password. When the submit button is clicked, the values of the two input fields are logged to the console. The &lt;code&gt;useState()&lt;/code&gt; hook is used to manage the state of the two input fields. Although, this code does what it's supposed to do, it also causes the component to re-render every time the input fields are changed. &lt;/p&gt;

&lt;p&gt;This is due to the usage of the &lt;code&gt;useState()&lt;/code&gt; hook, which by definition causes the component to re-render every time the state is changed. This is not a problem in this example, but in a more complex application, this can cause performance issues. To avoid this, we can use the &lt;code&gt;useRef()&lt;/code&gt; hook instead of &lt;code&gt;useState()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When to use &lt;code&gt;useRef()&lt;/code&gt; instead of &lt;code&gt;useState()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A rule of thumb is to use &lt;code&gt;useState&lt;/code&gt; when you need to re-render the component when the state changes and &lt;code&gt;useRef&lt;/code&gt; when you don't need to re-render the component when the state changes.&lt;br&gt;
Here are some examples of when to use &lt;code&gt;useRef&lt;/code&gt; instead of &lt;code&gt;useState&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you need to store a value that does not trigger a re-render when it is updated.&lt;/li&gt;
&lt;li&gt;When you need to store a value that is not used in the render method.&lt;/li&gt;
&lt;li&gt;When you need to store a value that persists for the lifetime of the component.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>How can I set the value of a select input in React?</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sun, 20 Nov 2022 10:00:00 +0000</pubDate>
      <link>https://dev.to/trinityyi/how-can-i-set-the-value-of-a-select-input-in-react-1pl2</link>
      <guid>https://dev.to/trinityyi/how-can-i-set-the-value-of-a-select-input-in-react-1pl2</guid>
      <description>&lt;h3&gt;
  
  
  Adding selected to an option
&lt;/h3&gt;

&lt;p&gt;A very common way of setting a &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; input's value is by adding a &lt;code&gt;selected&lt;/code&gt; attribute to one of its &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; elements. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Select&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selected&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;
      &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;readOnly&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;readonly&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;target&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="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;callback&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="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&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;text&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;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;
  
  
  Setting value for the select
&lt;/h3&gt;

&lt;p&gt;While this approach closely resembles HTML and feels intuitive, there is an easier way to do the same thing. &lt;a href="https://reactjs.org/docs/forms.html#the-select-tag"&gt;React&lt;/a&gt; provides us with a shared API between &lt;code&gt;&amp;lt;input type="text"&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; where we can use &lt;code&gt;value&lt;/code&gt; or &lt;code&gt;defaultValue&lt;/code&gt; (depending if the input is controlled or not) to set the field's value.&lt;/p&gt;

&lt;p&gt;Using this API, we minimize the effort of checking for the selected value, as well as making the code easier to read and update as necessary. Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Select&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selected&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;
      &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;readOnly&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;readonly&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;selected&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;target&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="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;callback&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="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&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;text&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Note that the above implementation uses &lt;code&gt;defaultValue&lt;/code&gt;, therefore it implies that the component is uncontrolled. You can convert this &lt;code&gt;Select&lt;/code&gt; component into a controlled component by using &lt;code&gt;value&lt;/code&gt; instead of &lt;code&gt;defaultValue&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Do you like short, high-quality code snippets and articles? So do we! Visit &lt;a href="https://www.30secondsofcode.org/"&gt;30 seconds of code&lt;/a&gt; for more articles like this one or follow us on &lt;a href="https://twitter.com/30secondsofcode"&gt;Twitter&lt;/a&gt; for daily JavaScript, React and Python snippets!&lt;/em&gt; 👨‍💻&lt;/p&gt;

</description>
      <category>react</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Tip: React conditional className, empty strings and null</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sun, 13 Nov 2022 10:00:00 +0000</pubDate>
      <link>https://dev.to/trinityyi/tip-react-conditional-classname-empty-strings-and-null-37be</link>
      <guid>https://dev.to/trinityyi/tip-react-conditional-classname-empty-strings-and-null-37be</guid>
      <description>&lt;p&gt;When developing React components, you often need to conditionally apply a &lt;code&gt;className&lt;/code&gt; attribute to one or more elements. Sometimes, you will have two or more possible values depending on a condition. But there are also times that you might apply a &lt;code&gt;className&lt;/code&gt; based on a condition or leave it completely empty otherwise.&lt;/p&gt;

&lt;p&gt;There is a correct way to handle a conditional empty className and an incorrect one. Surprisingly, the incorrect way is pretty common and examples of it can be found all around the web. Consider the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;enabled&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="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enabled&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Hi &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;);&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;OtherComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;enabled&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="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;enabled&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enabled&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Hi &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;OtherComponent&lt;/span&gt; &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&amp;gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&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;In this code example, we define two very similar components. Both of them conditionally set the &lt;code&gt;className&lt;/code&gt; of an element based on the value of the &lt;code&gt;enabled&lt;/code&gt; prop. The first one will set the &lt;code&gt;className&lt;/code&gt; to an empty string if &lt;code&gt;enabled&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt; and the second one will set it to &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The resulting output is pretty similar. However, if you carefully inspect the HTML, you will notice that the first one will render &lt;code&gt;&amp;lt;div class&amp;gt;Hi&amp;lt;/div&amp;gt;&lt;/code&gt; whereas the second one will render &lt;code&gt;&amp;lt;div&amp;gt;Hi&amp;lt;/div&amp;gt;&lt;/code&gt;. This kind of markup (an attribute being present but without value) is rather uncommon and you'd rarely ever see something like that without React. This subtle difference is quite important and might be the root of a lot of problems, especially when writing CSS selectors for elements with/without any classes (e.g. &lt;code&gt;[class]&lt;/code&gt;/&lt;code&gt;:not([class])&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Therefore, you should prefer &lt;code&gt;null&lt;/code&gt; when you don't want to add a &lt;code&gt;className&lt;/code&gt; to an element, instead of an empty string. It keeps the markup cleaner and might help prevent some potential issues.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Do you like short, high-quality code snippets and articles? So do we! Visit &lt;a href="https://www.30secondsofcode.org/"&gt;30 seconds of code&lt;/a&gt; for more articles like this one or follow us on &lt;a href="https://twitter.com/30secondsofcode"&gt;Twitter&lt;/a&gt; for daily JavaScript, React and Python snippets!&lt;/em&gt; 👨‍💻&lt;/p&gt;

</description>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>Tip: JavaScript array sorting shorthand</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sun, 06 Nov 2022 10:00:00 +0000</pubDate>
      <link>https://dev.to/trinityyi/tip-javascript-array-sorting-shorthand-oh8</link>
      <guid>https://dev.to/trinityyi/tip-javascript-array-sorting-shorthand-oh8</guid>
      <description>&lt;p&gt;When sorting an array of primitive values (e.g. strings or numbers), you'll often see a lot of code that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&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;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// Sort in ascending order&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&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="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="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// [0, 1, 2, 4, 5, 8]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this piece of code does the job, there is also a one-line alternative for it. The trick hinges on &lt;code&gt;Array.prototype.sort()&lt;/code&gt; expecting either a positive or a negative value to perform a swap between two elements, thus allowing for more flexible values than &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;-1&lt;/code&gt;. Subtracting the numeric values in an array is sufficient and can also be used to sort the array the other way around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&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;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// Sort in ascending order&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [0, 1, 2, 4, 5, 8]&lt;/span&gt;
&lt;span class="c1"&gt;// Sort in descending order&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;b&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [8, 5, 4, 2, 1, 0]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are working with string arrays, you should instead use &lt;code&gt;String.prototype.localeCompare()&lt;/code&gt;, as it provides far greater flexibility, by accounting for specific locales and their unique needs:&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;s&lt;/span&gt; &lt;span class="o"&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;Hi&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;Hola&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;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="c1"&gt;// Sort in ascending order&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localeCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// ['Hello', 'Hi', 'Hola']&lt;/span&gt;
&lt;span class="c1"&gt;// Sort in descending order&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localeCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// ['Hola', 'Hi', 'Hello']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Do you like short, high-quality code snippets and articles? So do we! Visit &lt;a href="https://www.30secondsofcode.org/"&gt;30 seconds of code&lt;/a&gt; for more articles like this one or follow us on &lt;a href="https://twitter.com/30secondsofcode"&gt;Twitter&lt;/a&gt; for daily JavaScript, React and Python snippets!&lt;/em&gt; 👨‍💻&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>How can I execute an event handler at most once?</title>
      <dc:creator>Isabelle M.</dc:creator>
      <pubDate>Sun, 30 Oct 2022 10:00:00 +0000</pubDate>
      <link>https://dev.to/trinityyi/how-can-i-execute-an-event-handler-at-most-once-2imc</link>
      <guid>https://dev.to/trinityyi/how-can-i-execute-an-event-handler-at-most-once-2imc</guid>
      <description>&lt;h3&gt;
  
  
  jQuery
&lt;/h3&gt;

&lt;p&gt;Back in the day when jQuery was all the rage, we would usually use &lt;a href="https://api.jquery.com/one/"&gt;&lt;code&gt;$.one()&lt;/code&gt;&lt;/a&gt; to create an event handler that would execute at most once for a given event per element. A simple example would be as follows:&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;id=&lt;/span&gt;&lt;span class="s"&gt;"my-btn"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&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;#my-btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;one&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="o"&gt;=&amp;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="nx"&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;Hello!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 'Hello!' will only be logged on the first click&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using a flag
&lt;/h3&gt;

&lt;p&gt;However, jQuery seems to have fallen out of favor lately and thus many developers have resorted to writing their version of &lt;code&gt;$.one()&lt;/code&gt;. An implementation could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listenOnce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fn&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;let&lt;/span&gt; &lt;span class="nx"&gt;fired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;fired&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;fired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;listenOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&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-btn&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;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="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="nx"&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;Hello!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 'Hello!' will only be logged on the first click&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this implementation, we use a flag, &lt;code&gt;fired&lt;/code&gt;, to check if the event has been triggered before and only execute the passed callback, &lt;code&gt;fn&lt;/code&gt;, the first time the event is triggered. There are some details that we might have omitted such as removing the listener, but overall this is a reasonably solid implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Event listener options
&lt;/h3&gt;

&lt;p&gt;If you are targeting modern browsers (i.e. not IE), &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener"&gt;&lt;code&gt;EventTarget.addEventListener()&lt;/code&gt;&lt;/a&gt; has introduced the &lt;code&gt;options&lt;/code&gt; object parameter, which allows us to pass a few different flags, one of which is &lt;code&gt;once&lt;/code&gt;. Setting &lt;code&gt;once&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; results in the exact same behavior as the snippet above with minimal effort.&lt;/p&gt;

&lt;p&gt;Here's one way to write the previous snippet using &lt;code&gt;once&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listenOnce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fn&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;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;once&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="nx"&gt;listenOnce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&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-btn&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;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="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="nx"&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;Hello!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 'Hello!' will only be logged on the first click&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Do you like short, high-quality code snippets and articles? So do we! Visit &lt;a href="https://www.30secondsofcode.org/"&gt;30 seconds of code&lt;/a&gt; for more articles like this one or follow us on &lt;a href="https://twitter.com/30secondsofcode"&gt;Twitter&lt;/a&gt; for daily JavaScript, React and Python snippets!&lt;/em&gt; 👨‍💻&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
