<?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: Lakshmi Bhargavi Gajula</title>
    <description>The latest articles on DEV Community by Lakshmi Bhargavi Gajula (@bhargavigajula).</description>
    <link>https://dev.to/bhargavigajula</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%2F3983009%2Facb994d6-868c-48d2-9c2a-69554e6ca56f.png</url>
      <title>DEV Community: Lakshmi Bhargavi Gajula</title>
      <link>https://dev.to/bhargavigajula</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bhargavigajula"/>
    <language>en</language>
    <item>
      <title>From Confused to Confident: How I Finally Mastered GitHub Copilot in Every Situation</title>
      <dc:creator>Lakshmi Bhargavi Gajula</dc:creator>
      <pubDate>Sat, 13 Jun 2026 18:16:14 +0000</pubDate>
      <link>https://dev.to/bhargavigajula/from-confused-to-confident-how-i-finally-mastered-github-copilot-in-every-situation-43lk</link>
      <guid>https://dev.to/bhargavigajula/from-confused-to-confident-how-i-finally-mastered-github-copilot-in-every-situation-43lk</guid>
      <description>&lt;h1&gt;
  
  
  From Confused to Confident: How I Finally Mastered GitHub Copilot in Every Situation
&lt;/h1&gt;

&lt;p&gt;I still remember the afternoon I rage-closed VS Code because Copilot kept suggesting the wrong function signatures — &lt;em&gt;again&lt;/em&gt;. I had been treating it like a magic oracle, typing vague comments and expecting perfect code to rain down from the AI heavens. Spoiler: that's not how it works.&lt;/p&gt;

&lt;p&gt;After weeks of trial, error, and a few embarrassing pull request reviews, I cracked the code (pun intended). Here's everything I wish someone had told me about using GitHub Copilot accurately — across &lt;strong&gt;Chat&lt;/strong&gt;, &lt;strong&gt;Plan&lt;/strong&gt;, and &lt;strong&gt;Agent&lt;/strong&gt; modes.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 First, Understand What Copilot Actually Is
&lt;/h2&gt;

&lt;p&gt;Before diving into tips, let's reset expectations. GitHub Copilot is not a search engine. It's not Stack Overflow with a fancy UI. It's a &lt;strong&gt;context-aware AI assistant&lt;/strong&gt; trained on massive amounts of code. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;quality of your output depends directly on the quality of your input&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It works best when it has rich context — open files, good comments, clear naming.&lt;/li&gt;
&lt;li&gt;It can be wrong. Confidently wrong. Always review what it generates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that mindset locked in, let's explore each mode.&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Copilot Chat: Your Pair Programmer in the Sidebar
&lt;/h2&gt;

&lt;p&gt;The first time I opened Copilot Chat, I typed: &lt;em&gt;"fix my code."&lt;/em&gt; It stared back at me, basically confused. Of course it was — I hadn't told it &lt;em&gt;which&lt;/em&gt; code, &lt;em&gt;what&lt;/em&gt; was broken, or &lt;em&gt;what&lt;/em&gt; I expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips for Accurate Chat Usage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Be specific and contextual.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why isn't this working?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Try:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This &lt;code&gt;useEffect&lt;/code&gt; hook in React runs on every render instead of only when &lt;code&gt;userId&lt;/code&gt; changes. Here's the code: [paste snippet]. What's wrong?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The more context you give, the more surgical the answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Use slash commands to guide intent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Copilot Chat supports built-in commands that dramatically improve accuracy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/explain   → Explains selected code in plain English
/fix       → Suggests a fix for a highlighted bug
/tests     → Generates unit tests for selected code
/doc       → Writes documentation for a function or class
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These aren't just shortcuts — they &lt;strong&gt;set the intent&lt;/strong&gt; so Copilot doesn't have to guess what you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Reference your files explicitly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In VS Code, you can use &lt;code&gt;#file:filename.js&lt;/code&gt; in the chat to attach a specific file as context. This is a game-changer when your bug spans multiple files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Iterate like a conversation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Don't expect perfection on the first response. Treat it like a real pair programmer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"That's close, but can you refactor it to use async/await instead of &lt;code&gt;.then()&lt;/code&gt;?"&lt;/li&gt;
&lt;li&gt;"Can you make this TypeScript-friendly?"&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🗺️ Copilot Plan: Think Before You Build
&lt;/h2&gt;

&lt;p&gt;This is the mode most developers skip — and it's the one that saves the most time.&lt;/p&gt;

&lt;p&gt;I once spent three hours building a feature, only to realize mid-implementation that my database schema made no sense for the use case. If I had &lt;em&gt;planned&lt;/em&gt; it with Copilot first, I would have caught that in ten minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is Plan Mode?
&lt;/h3&gt;

&lt;p&gt;Plan mode (available in Copilot Chat via &lt;code&gt;@workspace&lt;/code&gt; or structured prompting) lets you &lt;strong&gt;think through architecture, approach, and steps&lt;/strong&gt; before writing a single line of code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips for Accurate Plan Usage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Ask Copilot to outline an approach first.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"I want to build a real-time notification system using WebSockets in Node.js 
and React. Before writing any code, can you outline the architecture, 
key components, and potential pitfalls?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This forces a structured response you can critique &lt;em&gt;before&lt;/em&gt; investing time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Use it for breaking down complex tasks.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Break down the steps needed to migrate this REST API to GraphQL. 
List them in order with potential blockers for each step."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Validate the plan collaboratively.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once Copilot gives you a plan, push back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Is there a simpler approach?"&lt;/li&gt;
&lt;li&gt;"What would be the tradeoffs of using Redis here vs. in-memory storage?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dialogue sharpens the plan before a single keystroke hits your editor.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 Copilot Agent: Let It Drive (With Your Hands on the Wheel)
&lt;/h2&gt;

&lt;p&gt;Agent mode is where things get &lt;em&gt;wild&lt;/em&gt; — and where the most mistakes happen if you're not careful.&lt;/p&gt;

&lt;p&gt;I once let Copilot Agent run loose on a refactoring task with a vague prompt. It refactored alright — it refactored &lt;em&gt;everything&lt;/em&gt;, including files I didn't want touched. Lesson learned.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is Agent Mode?
&lt;/h3&gt;

&lt;p&gt;Copilot Agent (part of GitHub Copilot Workspace and the newer agentic features in VS Code) can &lt;strong&gt;autonomously complete multi-step tasks&lt;/strong&gt; — creating files, running terminal commands, editing across your codebase, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips for Accurate Agent Usage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Write precise, scoped prompts.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vague prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Refactor the project."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Precise prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Refactor only the &lt;code&gt;authService.ts&lt;/code&gt; file to replace callback-based functions with async/await. Do not modify any other files."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Scope your instructions like you're writing a ticket for a junior developer. Specific. Bounded. Clear.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Review every step before confirming.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Copilot Agent will often show you a &lt;strong&gt;plan of actions&lt;/strong&gt; before executing. Read it. Every line. It takes 30 seconds and can save you an hour of reverting changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Use it for repetitive, well-defined tasks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agent mode shines brightest on tasks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating boilerplate across multiple files&lt;/li&gt;
&lt;li&gt;Writing and running test suites&lt;/li&gt;
&lt;li&gt;Scaffolding a new feature following an existing pattern in the codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Keep your git history clean.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before running Agent on anything significant, &lt;strong&gt;commit your current state&lt;/strong&gt;. If something goes sideways, &lt;code&gt;git reset&lt;/code&gt; is your best friend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Always do this before letting the agent loose&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"checkpoint before copilot agent refactor"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔑 Universal Tips That Apply to Every Mode
&lt;/h2&gt;

&lt;p&gt;No matter which mode you're in, these principles hold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name things clearly.&lt;/strong&gt; Good variable and function names give Copilot massive context clues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write comments before code.&lt;/strong&gt; A comment like &lt;code&gt;// Fetch user data and cache it for 5 minutes&lt;/code&gt; gives Copilot a spec to work from.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't blindly accept suggestions.&lt;/strong&gt; Tab-complete is tempting. Review first, accept second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep your files focused.&lt;/strong&gt; Smaller, single-responsibility files produce better suggestions than 800-line monoliths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restart and refresh context&lt;/strong&gt; if suggestions start going off the rails — sometimes closing and reopening a file resets things.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏁 The Takeaway
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot went from feeling like a broken toy to being my most-used development tool — and the only thing that changed was &lt;em&gt;how I used it&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The secret isn't some hidden setting or magic prompt. It's treating Copilot like a &lt;strong&gt;brilliant but context-dependent collaborator&lt;/strong&gt;. Give it clear goals, good context, and boundaries — and it will genuinely accelerate your workflow.&lt;/p&gt;

&lt;p&gt;Start small: next time you open Chat, try a slash command. Next time you start a feature, ask Copilot to plan it first. And when you're ready for Agent mode, keep one hand on the git history.&lt;/p&gt;

&lt;p&gt;You've got a powerful co-pilot now. Time to actually fly.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have a Copilot tip that changed your workflow? Drop it in the comments — I'd love to add more tools to the toolkit.&lt;/em&gt; 🚀&lt;/p&gt;

</description>
      <category>githubcopilot</category>
      <category>productivity</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Stop Burning Through Claude Tokens: Practical Tips Every Developer Should Know</title>
      <dc:creator>Lakshmi Bhargavi Gajula</dc:creator>
      <pubDate>Sat, 13 Jun 2026 18:13:14 +0000</pubDate>
      <link>https://dev.to/bhargavigajula/stop-burning-through-claude-tokens-practical-tips-every-developer-should-know-he</link>
      <guid>https://dev.to/bhargavigajula/stop-burning-through-claude-tokens-practical-tips-every-developer-should-know-he</guid>
      <description>&lt;h1&gt;
  
  
  Stop Burning Through Claude Tokens: Practical Tips Every Developer Should Know
&lt;/h1&gt;

&lt;p&gt;If you've integrated Claude into your workflow or your app, you've probably had that moment — the bill arrives (or the rate limit hits), and you think: &lt;em&gt;where did all those tokens go?&lt;/em&gt; I've been there. And after spending an embarrassing amount of time optimizing prompts, restructuring conversations, and reading through Anthropic's documentation, I have some hard-won opinions to share.&lt;/p&gt;

&lt;p&gt;This isn't a dry technical rundown. These are real lessons from real (sometimes painful) experience. Let's get into it.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 First, Understand What You're Actually Paying For
&lt;/h2&gt;

&lt;p&gt;Before you can reduce token usage, you need to understand the two-sided nature of token billing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input tokens&lt;/strong&gt;: Everything you send to Claude — your system prompt, the conversation history, the user message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output tokens&lt;/strong&gt;: Everything Claude generates back.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the thing most developers underestimate: &lt;strong&gt;your system prompt and conversation history are re-sent on every single API call.&lt;/strong&gt; That silent, invisible re-transmission is often the biggest culprit behind bloated token usage, especially in multi-turn applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✂️ Tip #1: Trim Your System Prompt Ruthlessly
&lt;/h2&gt;

&lt;p&gt;System prompts are powerful, but they're also easy to let balloon out of control. I've seen system prompts that read like legal contracts — paragraphs of edge-case handling, personality descriptions, and disclaimers that Claude probably doesn't need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be surgical about it:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove redundant instructions. If you say "be concise" three times, once is enough.&lt;/li&gt;
&lt;li&gt;Cut examples unless they're truly necessary for format enforcement.&lt;/li&gt;
&lt;li&gt;Avoid explaining &lt;em&gt;why&lt;/em&gt; Claude should do something unless it genuinely affects the output quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A well-written system prompt should be the minimum viable instruction set. Treat it like code — refactor it regularly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Before (verbose)
You are a helpful assistant. You should always be polite and professional.
Never be rude to users. Make sure your responses are accurate and helpful.
Always try to answer the user's question. Be concise when possible.

# After (lean)
You are a concise, professional assistant. Answer questions accurately and briefly.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tiny cleanup can save hundreds of tokens per conversation when multiplied across thousands of calls.&lt;/p&gt;




&lt;h2&gt;
  
  
  🗂️ Tip #2: Manage Conversation History Strategically
&lt;/h2&gt;

&lt;p&gt;This one trips up a lot of developers building chat-based applications. By default, you're probably passing the entire conversation history to Claude on every turn. For long conversations, this gets expensive &lt;em&gt;fast&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strategies to handle this:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Sliding window&lt;/strong&gt;: Only pass the last N messages instead of the full history. Works well for most conversational use cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summarization&lt;/strong&gt;: Periodically ask Claude to summarize the conversation so far, then replace the raw history with that summary. You keep context without the token overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relevant retrieval&lt;/strong&gt;: For knowledge-heavy apps, use vector search to pull only the relevant past messages rather than the whole thread.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There's no one-size-fits-all answer here — it depends on your use case. But ignoring history management entirely is almost always a mistake.&lt;/p&gt;




&lt;h2&gt;
  
  
  📏 Tip #3: Ask for Shorter Outputs Explicitly
&lt;/h2&gt;

&lt;p&gt;Claude is trained to be thorough and helpful, which is great — until you're paying for 800 tokens when 200 would have done the job. Claude won't automatically be terse unless you tell it to be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try being explicit:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Answer in 2-3 sentences."&lt;/li&gt;
&lt;li&gt;"Respond with only the code, no explanation."&lt;/li&gt;
&lt;li&gt;"Give me a bullet list, max 5 items."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This feels obvious, but it's surprising how many prompts just ask a question and hope for a brief answer. Claude interprets open-ended questions as an invitation to be comprehensive. Set expectations clearly.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Tip #4: Watch Out for the Context Window Trap
&lt;/h2&gt;

&lt;p&gt;Here's something to be careful about: &lt;strong&gt;just because Claude has a large context window doesn't mean you should use all of it carelessly.&lt;/strong&gt; Stuffing the context with huge documents, long code files, or massive conversation histories might &lt;em&gt;work&lt;/em&gt;, but it's often wasteful.&lt;/p&gt;

&lt;p&gt;Before dumping a 10,000-token document into your prompt, ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does Claude actually need &lt;em&gt;all&lt;/em&gt; of this information?&lt;/li&gt;
&lt;li&gt;Can I extract the relevant section instead?&lt;/li&gt;
&lt;li&gt;Could I use a retrieval strategy instead of brute-force context stuffing?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Big context windows are a capability, not an excuse to skip thoughtful prompt design.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Tip #5: Batch When You Can
&lt;/h2&gt;

&lt;p&gt;If you're running repetitive tasks — classifying a list of items, summarizing multiple documents, extracting structured data from records — consider batching them into a single prompt rather than making individual API calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Instead of this (3 separate calls)
Classify the sentiment of: "I love this product!"
Classify the sentiment of: "This is terrible."
Classify the sentiment of: "It's okay I guess."

# Do this (1 call)
Classify the sentiment of each sentence below. Reply with a JSON array.
1. "I love this product!"
2. "This is terrible."
3. "It's okay I guess."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Batching reduces per-call overhead from system prompts and saves on round-trip latency too. Win-win.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚩 Things to Be Careful About
&lt;/h2&gt;

&lt;p&gt;Beyond token usage, there are a few broader habits worth watching:&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't Over-rely on Claude for Simple Tasks
&lt;/h3&gt;

&lt;p&gt;If you're using Claude to do string formatting, basic math, or simple lookups — you're probably over-engineering it. Use Claude where reasoning, language understanding, or generation actually matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompt Injection is a Real Risk
&lt;/h3&gt;

&lt;p&gt;If you're building an app that feeds user-provided content directly into Claude's context, be aware of prompt injection attacks. Users can craft inputs designed to override your system prompt or manipulate Claude's behavior. Always sanitize and think carefully about what user content ends up in your prompts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't Assume Consistency Without Testing
&lt;/h3&gt;

&lt;p&gt;Claude is not a deterministic function. The same prompt can produce slightly different results, especially at higher temperature settings. If consistency matters in your app (structured data extraction, for example), test extensively and consider using structured output formats or validation layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching is Your Friend
&lt;/h3&gt;

&lt;p&gt;If you're using the API and making repeated calls with identical or near-identical system prompts and context, look into &lt;strong&gt;prompt caching&lt;/strong&gt; (available via Anthropic's API). It can dramatically reduce costs for repetitive workloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Using Claude effectively isn't just about getting good outputs — it's about being intentional with every token you send and receive. The developers who get the most out of Claude (at the lowest cost) are the ones who treat prompting like engineering: iterative, measured, and always looking for inefficiencies to cut.&lt;/p&gt;

&lt;p&gt;Here's my honest take: &lt;strong&gt;most token waste is preventable.&lt;/strong&gt; Bloated system prompts, unmanaged conversation history, and vague output instructions account for the majority of unnecessary spending I've seen. Fix those three things first, and you'll probably see a significant drop in usage before you need to do anything more sophisticated.&lt;/p&gt;

&lt;p&gt;Start small, measure your token counts, and iterate. Claude is a genuinely powerful tool — treat it like one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>productivity</category>
      <category>tips</category>
    </item>
    <item>
      <title>Power Apps Components Explained: Build Reusable UI Like a Pro</title>
      <dc:creator>Lakshmi Bhargavi Gajula</dc:creator>
      <pubDate>Sat, 13 Jun 2026 18:10:00 +0000</pubDate>
      <link>https://dev.to/bhargavigajula/power-apps-components-explained-build-reusable-ui-like-a-pro-47a5</link>
      <guid>https://dev.to/bhargavigajula/power-apps-components-explained-build-reusable-ui-like-a-pro-47a5</guid>
      <description>&lt;h1&gt;
  
  
  Power Apps Components Explained: Build Reusable UI Like a Pro
&lt;/h1&gt;

&lt;p&gt;Imagine building a form in Power Apps, perfecting the styling, adding validation logic, and then realizing you need the exact same form in five other screens. You copy it. Then a design change comes in, and you have to update all five copies manually. Sound familiar? That's the problem &lt;strong&gt;Power Apps Components&lt;/strong&gt; solve — and once you understand them, you'll wonder how you ever built apps without them.&lt;/p&gt;

&lt;p&gt;In this post, we'll break down what components are, how they work, and how to build one from scratch. Whether you're coming from traditional software development or exploring the low-code space for the first time, this guide has you covered.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Components in Power Apps?
&lt;/h2&gt;

&lt;p&gt;Components in Power Apps are &lt;strong&gt;reusable UI building blocks&lt;/strong&gt; — think of them like custom controls or widgets. They're similar in concept to components in React or Angular: you define them once, and you can drop them into any screen (or even share them across apps).&lt;/p&gt;

&lt;p&gt;Key characteristics of Power Apps Components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encapsulated logic and UI&lt;/strong&gt; — the component manages its own behavior internally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom properties&lt;/strong&gt; — you can define inputs and outputs to communicate with the parent app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusable across screens&lt;/strong&gt; — place the same component on multiple screens without duplicating logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component Libraries&lt;/strong&gt; — share components across multiple apps in your organization.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Components vs. Screens vs. Controls
&lt;/h2&gt;

&lt;p&gt;Before diving deeper, let's clarify the hierarchy:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Screen&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A full page/view in your app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A built-in element (Button, TextInput, Gallery, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Component&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A custom, reusable group of controls with its own properties&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Components sit between controls and screens. They're composed of built-in controls but behave like a single, self-contained unit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating Your First Component
&lt;/h2&gt;

&lt;p&gt;Let's build a simple &lt;strong&gt;Header Bar Component&lt;/strong&gt; that accepts a title and a background color as inputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Enable Components (if needed)
&lt;/h3&gt;

&lt;p&gt;In older environments, you may need to enable the Components feature:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;File &amp;gt; Settings &amp;gt; Advanced Settings&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Toggle on &lt;strong&gt;Components&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In most modern Power Apps Studio, this is enabled by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create a New Component
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open Power Apps Studio and open (or create) a Canvas App.&lt;/li&gt;
&lt;li&gt;In the left panel, click the &lt;strong&gt;Tree View&lt;/strong&gt; icon.&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Components&lt;/strong&gt; tab at the top of the Tree View.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;+ New Component&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You'll see a blank canvas — this is your component's design surface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Add Custom Input Properties
&lt;/h3&gt;

&lt;p&gt;Components communicate with the outside world through &lt;strong&gt;custom properties&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;With your component selected, click &lt;strong&gt;New custom property&lt;/strong&gt; in the right panel.&lt;/li&gt;
&lt;li&gt;Create a property called &lt;code&gt;HeaderTitle&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Display name:&lt;/strong&gt; HeaderTitle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Property type:&lt;/strong&gt; Input&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data type:&lt;/strong&gt; Text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default value:&lt;/strong&gt; &lt;code&gt;"My App"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Create another property called &lt;code&gt;BackgroundColor&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Display name:&lt;/strong&gt; BackgroundColor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Property type:&lt;/strong&gt; Input&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data type:&lt;/strong&gt; Color&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default value:&lt;/strong&gt; &lt;code&gt;RGBA(0, 120, 212, 1)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4: Design the Component
&lt;/h3&gt;

&lt;p&gt;Now add controls inside the component:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Insert a &lt;strong&gt;Rectangle&lt;/strong&gt; control and set its properties:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fill: HeaderBar.BackgroundColor
Width: Parent.Width
Height: 60
X: 0
Y: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Insert a &lt;strong&gt;Label&lt;/strong&gt; control on top of the rectangle:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Text: HeaderBar.HeaderTitle
Color: White
FontWeight: Bold
X: 16
Y: 0
Height: 60
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Inside a component, you reference your custom input properties using the component's name followed by the property name (e.g., &lt;code&gt;HeaderBar.HeaderTitle&lt;/code&gt;).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Using the Component in Your App
&lt;/h2&gt;

&lt;p&gt;Now that the component is built, let's use it on a screen.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go back to the &lt;strong&gt;Screens&lt;/strong&gt; tab in Tree View.&lt;/li&gt;
&lt;li&gt;Select a screen.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Insert &amp;gt; Custom&lt;/strong&gt; — your component will appear in the list.&lt;/li&gt;
&lt;li&gt;Insert it onto the screen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You'll immediately see it render. Now customize it via the properties panel on the right:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HeaderTitle: "Dashboard"
BackgroundColor: RGBA(50, 50, 50, 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every instance of the component can have different values — just like passing props in React.&lt;/p&gt;




&lt;h2&gt;
  
  
  Output Properties: Getting Data Back Out
&lt;/h2&gt;

&lt;p&gt;Components aren't just for display. You can also define &lt;strong&gt;Output properties&lt;/strong&gt; to send data back to the parent screen.&lt;/p&gt;

&lt;p&gt;Example use case: A custom date picker component that exposes the selected date.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a custom property:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Display name:&lt;/strong&gt; SelectedDate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Property type:&lt;/strong&gt; Output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data type:&lt;/strong&gt; DateTime&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the component, bind a &lt;code&gt;DatePicker&lt;/code&gt; control's value to this output:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// In the component, set the Output property formula:
SelectedDate = DatePickerControl.SelectedDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;On your screen, you can now reference it like:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Text: MyDatePickerComponent.SelectedDate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a clean, predictable data flow between your component and the screen.&lt;/p&gt;




&lt;h2&gt;
  
  
  Component Libraries: Sharing Across Apps
&lt;/h2&gt;

&lt;p&gt;The real power unlocks when you use &lt;strong&gt;Component Libraries&lt;/strong&gt; — a dedicated environment asset that lets multiple apps consume the same components.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Create a Component Library
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://make.powerapps.com" rel="noopener noreferrer"&gt;make.powerapps.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;+ Create &amp;gt; Component Library&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Build your components inside the library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publish&lt;/strong&gt; the library.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How to Use a Component Library in an App
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In Power Apps Studio, go to &lt;strong&gt;Insert &amp;gt; Get more components&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Browse to your Component Library.&lt;/li&gt;
&lt;li&gt;Import the component — it now appears under &lt;strong&gt;Library Components&lt;/strong&gt; in the Insert menu.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you update the library and publish, apps using it will receive a &lt;strong&gt;notification to update&lt;/strong&gt; — similar to a package version update in npm.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices for Power Apps Components
&lt;/h2&gt;

&lt;p&gt;Here are some developer-friendly tips to keep your component architecture clean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name components clearly&lt;/strong&gt; — use PascalCase like &lt;code&gt;HeaderBar&lt;/code&gt;, &lt;code&gt;NavMenu&lt;/code&gt;, &lt;code&gt;SearchCard&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep components focused&lt;/strong&gt; — one component, one responsibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid deeply nested components&lt;/strong&gt; — Power Apps has a nesting limit and performance can degrade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document custom properties&lt;/strong&gt; — use the Description field when creating properties to help teammates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Component Libraries for organization-wide standards&lt;/strong&gt; — maintain a design system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test components in isolation&lt;/strong&gt; before embedding them in complex screens.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Limitations to Be Aware Of
&lt;/h2&gt;

&lt;p&gt;Power Apps components are powerful but have some gotchas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No behavioral properties by default&lt;/strong&gt; (though this can be enabled in some environments) — passing functions as properties is limited compared to code-based frameworks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component nesting&lt;/strong&gt; has limits — you can't infinitely nest components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context variables and collections&lt;/strong&gt; defined outside a component aren't automatically accessible inside it. You need to explicitly pass them via input properties.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component Library updates&lt;/strong&gt; are not automatic — app makers must opt-in to accept updates.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Power Apps Components bring a &lt;strong&gt;developer-friendly, modular mindset&lt;/strong&gt; to the low-code world. By encapsulating UI and logic into reusable, property-driven units, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eliminate duplication&lt;/strong&gt; across screens and apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enforce consistency&lt;/strong&gt; in UI design.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed up development&lt;/strong&gt; by reusing proven building blocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplify maintenance&lt;/strong&gt; — fix once, update everywhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building anything beyond a simple one-screen app, components should be part of your Power Apps toolkit. Start small — extract something you've already duplicated into a component — and you'll immediately feel the difference.&lt;/p&gt;

&lt;p&gt;Happy building! 🚀&lt;/p&gt;

</description>
      <category>powerapps</category>
      <category>lowcode</category>
      <category>components</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>A11y Testing: The Missing Piece in Your QA Workflow</title>
      <dc:creator>Lakshmi Bhargavi Gajula</dc:creator>
      <pubDate>Sat, 13 Jun 2026 18:07:08 +0000</pubDate>
      <link>https://dev.to/bhargavigajula/a11y-testing-the-missing-piece-in-your-qa-workflow-ljd</link>
      <guid>https://dev.to/bhargavigajula/a11y-testing-the-missing-piece-in-your-qa-workflow-ljd</guid>
      <description>&lt;h1&gt;
  
  
  A11y Testing: The Missing Piece in Your QA Workflow
&lt;/h1&gt;

&lt;p&gt;Let me ask you something: when was the last time you thought about accessibility testing in your project? If your answer is "never" or "I meant to get around to that," you're definitely not alone. Most of us are pretty good at writing unit tests, maybe some integration tests — but &lt;strong&gt;a11y (accessibility) tests&lt;/strong&gt;? That's the one that tends to fall through the cracks.&lt;/p&gt;

&lt;p&gt;Today I want to share what I learned about a11y testing — what it is, why it matters more than you probably think, and how you can actually start doing it without turning your whole workflow upside down.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Even Is A11y Testing?
&lt;/h2&gt;

&lt;p&gt;First things first — "a11y" is a numeronym for &lt;strong&gt;accessibility&lt;/strong&gt;. The "11" represents the 11 letters between the "a" and the "y". Nerdy? Yes. Useful shorthand? Absolutely.&lt;/p&gt;

&lt;p&gt;Accessibility testing is the practice of checking whether your web application (or any software, really) can be used by people with disabilities. That includes people who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use screen readers (like NVDA or VoiceOver)&lt;/li&gt;
&lt;li&gt;Navigate with a keyboard instead of a mouse&lt;/li&gt;
&lt;li&gt;Have low vision and rely on high contrast or zoomed interfaces&lt;/li&gt;
&lt;li&gt;Have cognitive or motor disabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to make sure your app follows standards — primarily the &lt;strong&gt;WCAG (Web Content Accessibility Guidelines)&lt;/strong&gt; — so that everyone can use what you've built.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Should Developers Care?
&lt;/h2&gt;

&lt;p&gt;Here's the honest answer: because it's the right thing to do &lt;em&gt;and&lt;/em&gt; it's increasingly the smart business move.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;~1 in 4 adults&lt;/strong&gt; in the US has some form of disability (CDC data)&lt;/li&gt;
&lt;li&gt;Inaccessible apps can create &lt;strong&gt;legal liability&lt;/strong&gt; — lawsuits around web accessibility have been rising steadily&lt;/li&gt;
&lt;li&gt;Good accessibility practices often improve &lt;strong&gt;SEO and overall UX&lt;/strong&gt; for everyone&lt;/li&gt;
&lt;li&gt;It's way cheaper to &lt;strong&gt;build it right from the start&lt;/strong&gt; than to retrofit it later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And beyond the numbers: imagine building something you're proud of that a chunk of your users simply can't use. That's a problem worth solving.&lt;/p&gt;




&lt;h2&gt;
  
  
  Types of A11y Tests
&lt;/h2&gt;

&lt;p&gt;Not all accessibility testing looks the same. There are basically three flavors:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Automated Testing
&lt;/h3&gt;

&lt;p&gt;Tools that scan your code or rendered DOM and flag common accessibility violations automatically. Think of it as a linter, but for accessibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Popular tools:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/dequelabs/axe-core" rel="noopener noreferrer"&gt;&lt;code&gt;axe-core&lt;/code&gt;&lt;/a&gt; — the most widely used accessibility engine&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nickcolley/jest-axe" rel="noopener noreferrer"&gt;&lt;code&gt;jest-axe&lt;/code&gt;&lt;/a&gt; — integrates axe into Jest tests&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/testing-library/jest-dom" rel="noopener noreferrer"&gt;&lt;code&gt;@testing-library/jest-dom&lt;/code&gt;&lt;/a&gt; — helpful matchers for accessible queries&lt;/li&gt;
&lt;li&gt;Lighthouse (built into Chrome DevTools)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a quick example of using &lt;code&gt;jest-axe&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;axe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toHaveNoViolations&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest-axe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toHaveNoViolations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should have no accessibility violations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyButton&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Click me&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;axe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveNoViolations&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Seriously. You add that test, run your suite, and you'll get a detailed report if anything fails accessibility checks.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Manual Testing
&lt;/h3&gt;

&lt;p&gt;Automated tools are great, but they only catch &lt;strong&gt;around 30-40% of accessibility issues&lt;/strong&gt;. The rest require a human.&lt;/p&gt;

&lt;p&gt;Manual testing means things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tabbing through your UI with just a keyboard&lt;/li&gt;
&lt;li&gt;Running a screen reader (NVDA on Windows, VoiceOver on Mac) and actually listening to your page&lt;/li&gt;
&lt;li&gt;Checking color contrast ratios manually&lt;/li&gt;
&lt;li&gt;Testing with browser zoom set to 200%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's a bit more effort, but it's genuinely eye-opening. You'll probably discover UI quirks you never noticed before.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. User Testing
&lt;/h3&gt;

&lt;p&gt;The gold standard. Actually getting feedback from users who have disabilities and rely on assistive technology day-to-day. This isn't always feasible for every team, but if you can do it — do it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started: Low-Hanging Fruit
&lt;/h2&gt;

&lt;p&gt;You don't have to overhaul everything overnight. Here are some quick wins you can implement today:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use semantic HTML.&lt;/strong&gt; This one is free and incredibly impactful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Bad --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"handleClick()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Good --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Screen readers know what a &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; is. A &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; with a click handler? Not so much.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add &lt;code&gt;alt&lt;/code&gt; text to images.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Bad --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"profile.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Good --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"profile.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Profile photo of Jane Doe"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Make sure form inputs have labels.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Bad --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Enter email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Good --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Email address&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Don't rely on color alone&lt;/strong&gt; to communicate information. Add icons, text, or patterns as a backup.&lt;/p&gt;




&lt;h2&gt;
  
  
  Integrating A11y Tests Into Your CI Pipeline
&lt;/h2&gt;

&lt;p&gt;Once you've written a few a11y tests, you'll want to make sure they run automatically so regressions don't sneak in. Most CI setups (GitHub Actions, GitLab CI, CircleCI) will just pick them up as part of your regular test run if you're using Jest.&lt;/p&gt;

&lt;p&gt;You can also add Lighthouse CI for automated audits on every pull request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/lighthouse.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lighthouse CI&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;lhci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Lighthouse CI&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;treosh/lighthouse-ci-action@v10&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;urls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;http://localhost:3000&lt;/span&gt;
          &lt;span class="na"&gt;budgetPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./budget.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, accessibility scores become part of your pull request feedback loop — just like test coverage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common A11y Mistakes Developers Make
&lt;/h2&gt;

&lt;p&gt;Before I wrap up, here's a quick hit list of the most common slip-ups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Missing or generic &lt;code&gt;alt&lt;/code&gt; text (e.g., &lt;code&gt;alt="image"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;❌ Low color contrast between text and background&lt;/li&gt;
&lt;li&gt;❌ Interactive elements that aren't keyboard-focusable&lt;/li&gt;
&lt;li&gt;❌ No &lt;code&gt;aria-label&lt;/code&gt; on icon-only buttons&lt;/li&gt;
&lt;li&gt;❌ Modals that trap focus or don't return focus on close&lt;/li&gt;
&lt;li&gt;❌ Auto-playing media without controls&lt;/li&gt;
&lt;li&gt;❌ Forms that only show errors in red (no text description)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many of these are easy fixes once you know to look for them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;A11y testing doesn't have to be this massive, intimidating undertaking. Start small — drop &lt;code&gt;jest-axe&lt;/code&gt; into one component test, run your page through Lighthouse, tab through your nav bar. You'll be surprised what you find, and you'll start building better habits from there.&lt;/p&gt;

&lt;p&gt;The web is for everyone. As developers, we have more power than almost anyone to make that actually true. Accessibility testing is one of the most practical ways to act on that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated tools like &lt;code&gt;axe-core&lt;/code&gt; and &lt;code&gt;jest-axe&lt;/code&gt; make a11y testing approachable&lt;/li&gt;
&lt;li&gt;Automated tests only catch ~30-40% of issues — manual testing fills the gap&lt;/li&gt;
&lt;li&gt;Semantic HTML is your best friend and costs you nothing&lt;/li&gt;
&lt;li&gt;Bake a11y checks into your CI pipeline so you catch regressions early&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now go make something everyone can use. 🙌&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>testing</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Stop Memory Leaks in Their Tracks: React useEffect Cleanup Explained</title>
      <dc:creator>Lakshmi Bhargavi Gajula</dc:creator>
      <pubDate>Sat, 13 Jun 2026 17:59:17 +0000</pubDate>
      <link>https://dev.to/bhargavigajula/stop-memory-leaks-in-their-tracks-react-useeffect-cleanup-explained-47a5</link>
      <guid>https://dev.to/bhargavigajula/stop-memory-leaks-in-their-tracks-react-useeffect-cleanup-explained-47a5</guid>
      <description>&lt;h1&gt;
  
  
  Stop Memory Leaks in Their Tracks: React useEffect Cleanup Explained
&lt;/h1&gt;

&lt;p&gt;If you've spent any time with React, you've probably seen this warning pop up in your console:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Warning: Can't perform a React state update on an unmounted component."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yeah, that one. It's a classic memory leak caused by async operations inside &lt;code&gt;useEffect&lt;/code&gt; — and it's way more common than you'd think. Let's break down what's actually happening and how to fix it cleanly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's the Problem?
&lt;/h2&gt;

&lt;p&gt;When you kick off an async operation (like a &lt;code&gt;fetch&lt;/code&gt; call) inside &lt;code&gt;useEffect&lt;/code&gt;, there's a race condition waiting to happen. If the component unmounts &lt;em&gt;before&lt;/em&gt; the async call finishes, React will still try to update state on something that no longer exists in the DOM.&lt;/p&gt;

&lt;p&gt;Here's a simple example of the problematic pattern:&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 💥 component might already be gone!&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No cleanup = potential memory leak.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: Return a Cleanup Function
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; lets you return a cleanup function that runs when the component unmounts (or before the effect re-runs). The trick with async calls is to use an &lt;strong&gt;abort flag&lt;/strong&gt; or the built-in &lt;code&gt;AbortController&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option 1: Boolean Flag
&lt;/h3&gt;

&lt;p&gt;Simple and straightforward:&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="nf"&gt;useEffect&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;isMounted&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&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;isMounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ✅ only update if still mounted&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;isMounted&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="c1"&gt;// cleanup!&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option 2: AbortController (the Modern Way)
&lt;/h3&gt;

&lt;p&gt;This one actually &lt;em&gt;cancels&lt;/em&gt; the fetch request, which is even better:&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AbortError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ignore abort errors&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// cancel the request on cleanup&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the preferred approach because it actually stops the network request rather than just ignoring the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Rules to Live By
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always&lt;/strong&gt; return a cleanup function from &lt;code&gt;useEffect&lt;/code&gt; when dealing with async operations, subscriptions, or timers.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;AbortController&lt;/code&gt; for fetch calls when possible.&lt;/li&gt;
&lt;li&gt;Use a boolean flag as a fallback for non-cancellable async operations.&lt;/li&gt;
&lt;li&gt;Watch your dependency array — missing deps can cause stale closures and unexpected behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Does This Actually Matter?
&lt;/h2&gt;

&lt;p&gt;Beyond silencing console warnings, proper cleanup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prevents unnecessary re-renders&lt;/strong&gt; that tank performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoids setting state on unmounted components&lt;/strong&gt;, which can cause subtle bugs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cancels in-flight network requests&lt;/strong&gt;, saving bandwidth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's one of those things that seems minor until it causes a weird bug in production at 2am.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; cleanup function is your best friend when working with async code in React. Whether you go with the &lt;code&gt;AbortController&lt;/code&gt; approach or a simple boolean flag, the key takeaway is this: &lt;strong&gt;always think about what happens when your component disappears before your async work is done.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Get into the habit of writing your cleanup from the start, and you'll save yourself a lot of headaches down the road. Your future self will thank you. 🙌&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>hooks</category>
    </item>
  </channel>
</rss>
